简单的redux示例:
// 第一步 定义计算规则,即 reducer
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
// 第二步 根据计算规则生成 store
let store = createStore(counter)
// 第三步 定义数据(即 state)变化之后的派发规则
store.subscribe(() => {
console.log('current state', store.getState())
})
// 第四步 触发数据变化
store.dispatch({type: 'INCREMENT'})
store.dispatch({type: 'INCREMENT'})
store.dispatch({type: 'DECREMENT'})
第一,要通过一个函数来触发数据的变化,即dispatch
,触发的时候一定要符合之前定制的规则,否则无效。第二,数据一旦发生变化时,会导致怎样后果,即subscribe
中定义的函数会执行。第三,如何取得当前的数据,即store.getState()
。
1、定义reducer
- 定义具体规则 userinfo
import * as actionTypes from '../constants/userinfo'
const initialState = {}
export default function userinfo(state = initialState, action) {
switch (action.type) {
// 登录
case actionTypes.USERINFO_LOGIN:
return action.data
// 修改城市
case actionTypes.UPDATE_CITYNAME:
return action.data
default:
return state
}
}
- 对所有的reducer 封装,对外提供统一的接口
import { combineReducers } from 'redux'
import userinfo from './userinfo'
const rootReducer = combineReducers({
userinfo
})
export default rootReducer
2、定义store
import { createStore } from 'redux'
import rootReducer from '../reducers'
export default function configureStore(initialState) {
const store = createStore(rootReducer, initialState,
// 触发 redux-devtools
window.devToolsExtension ? window.devToolsExtension() : undefined
)
return store
}
3、结合react,程序的入口文件app/index.jsx
import { Provider } from 'react-redux'
import configureStore from './store/configureStore'
import Hello from './containers/Hello'
const store = configureStore()
render(
<Provider store={store}>
<Hello/>
</Provider>,
document.getElementById('root')
)
store通过 react-redux的Provider组件派发到Hello组件中
4、定义action,action是行为的抽象,必须有一个type属性
export function login(data) {
return {
type: actionTypes.USERINFO_LOGIN,
data
}
}
export function updateCityName(data) {
return {
type: actionTypes.UPDATE_CITYNAME,
data
}
}
5、Hello组件中使用reducer和action
- 将reducer和action当作props传入到Hello中
import * as userinfoActions from '../actions/userinfo'
function mapStateToProps(state) {
return {
userinfo: state.userinfo
}
}
function mapDispatchToProps(dispatch) {
return {
userinfoActions: bindActionCreators(userinfoActions, dispatch)
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Hello)
- Hello中通过this.props.userinfo和this.props.userinfoActions获取数据和action
class Hello extends React.Component {
render() {
return (
<div>
<p>hello world</p>
<hr/>
<A userinfo={this.props.userinfo}/>
<hr/>
<B userinfo={this.props.userinfo}/>
<hr/>
<C actions={this.props.userinfoActions}/>
</div>
)
}
componentDidMount() {
// 模拟登陆 此处会触发数据变化,aciton中login的type对应reducer中的type,然后reducer响应type的操作是返回data,然后派发规则mapStateToProps,返回数据到props中。
this.props.userinfoActions.login({
userid: 'abc',
city: 'beijing'
})
}
}
mapStateToProps 如果这个没有传这个参数,那么组件就不会监听Redux store.
其实原因很简单,由于connect中只有mapStateToProps(state, [ownProps])
是根据redux store state的改变进行改变的,而像mapDispatchToProps(dispatch, [ownProps])
和mergeProps(stateProps, dispatchProps, ownProps)
都和redux store无关,所以如果mapStateToProps没有传的话,就不需要去监听redux store。