redux作为状态管理器在构建复杂应用的时候很有用,官网地址:https://redux.js.org
redux 主要有action、reducer、store
// 定义action
const ADD_COUNT = '增加数量'
const REMOVE_COUNT = '减少数量'
// action creator
const addCount = ()=>({type: ADD_COUNT})
const removeCount = ()=>({type: REMOVE_COUNT})
action 实际上就是一个对象 里面有我们要操作的 类型(type)就是要搞什么事情 通常以function的方式书写 方便调用传值等
// 初始状态
let initialState = {
count: 1
}
// 定义reducer
function counter(state=initialState, action) {
switch(action.type) {
case ADD_COUNT:
return {...state, count: state.count + 1}
break;
case REMOVE_COUNT:
return {...state, count: state.count-1}
break;
default:
return {...state}
break;
}
}
定义reducer 是一个函数:有两个参数(固定写法),第一个为当前的状态值 如果没有为初始状态值、第二个参数为action,这个action有一个type属性 代表要干不同的事情 这个方法要做的事情 就是返回新的state 要注意不能覆盖原来的state 所以这里用了解构的方式。
然后就是生成一个store 这要借助{ createStore } from 'redux'、和前面我们定义的reducer函数,createStore接受第一个参数就是我们的reducer
let store = createStore(counter)
好了 到目前为止 store就创建好了 下面就是使用了
ReactDOM.render(<App store={store} addCount={addCount} removeCount={removeCount} />, document.getElementById('root'))
我们将我们定义好的store 和 我们的 action 都当做App这个组件的属性传递过去 我们就可以直接在组件里面定义了
class App extends React.Component{
render(){
const {store, addCount, removeCount} = store
const count = store.getState().count
return (
<div>
<h1>当前数量: {count}</h1>
<hr />
<button onClick={store.dispatch(addCount())}>增加</button>
<button onClick={store.dispatch(removeCount())}>减少</button>
</div>
);
}
}
注意这里使用的是store.dispatch方法 这个方法接受的就是action 由于我们的addCount、removeCount都是函数所以需要调用一下、这个时候当我们点击增加 或减少的时候 就会触发store状态发生改变 但此时 由于render方法不会随着state的改变而改变所以我们需要 手动触发 我们将ReactDOM.render改写、同时借助store.subscribe这个订阅方法
function render () {
ReactDOM.render(<App store={store} addCount={addCount} removeCount={removeCount} />, document.getElementById('root'))
}
render()
store.subscribe(render)
这样子在改变state的时候就能够触发 render
。。。。。。。。。
当时就目前还说这个store用起来比较麻烦 而且当子组件多了之后一层一层的床底比较麻烦 所以我们现在借助react-redux来改写一下
首先安装: npm install -S react-redux 或者 yarn add react-redux
import { Provider } from 'react-redux'
ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'))
这个时候就不需要subscribe了 具体用法可以参考:https://react-redux.js.org/docs/introduction/quick-start
然后我们在App组件内 import { connect } from 'react-redux' 来链接组件和redux
import { connect } from 'react-redux';
class App extends React.Component{
render(){
console.log(this.props)
return (
<div>
<h1>当前数量: {this.props.count}</h1>
<hr />
<button onClick={this.props.addCount}>增加</button>
<button onClick={this.props.removeCount}>减少</button>
<button onClick={this.props.addCountAsync}>过两秒增加</button>
</div>
);
}
}
// 定义mapStateToProps将状态转化为组件的属性
const mapStateToProps = state=>({count: state.count})
// 定义mapDispatchToProps
// 将action转化为组件的属性 这里的action 在组建内部就等价于 store.dispatch(action)
const mapDispatchToProps = {addCount, removeCount}
// 通过 connect 链接 connect 实际上是一个高阶组件 传递一个组价返回一个新的组件
export default connect(mapStateToProps, mapDispatchToProps)(App)
下面是使用es7装饰器的写法
@connect(state=>({count: state.count}), {addCount, removeCount})
class App extends React.Component{
render(){
console.log(this.props)
return (
<div>
<h1>当前数量: {this.props.count}</h1>
<hr />
<button onClick={this.props.addCount}>增加</button>
<button onClick={this.props.removeCount}>减少</button>
<button onClick={this.props.addCountAsync}>过两秒增加</button>
</div>
);
}
}
文章结尾分享下 redux的异步操作,这里是借用react-thunk详细地址:https://www.npmjs.com/package/redux-thunk
首先react-thunk 提供了一个thunk的中间件 redux提供了applyMiddleware的方法使用中间件applyMiddleware(thunk)
我们在创建store的时候 改写成这样子:
let store = createStore(counter, applyMiddleware(thunk))
然后 我们定义一个异步的action
const addCountAsync = ()=>dispatch=>{
setTimeout(()=>{
dispatch(addCount())
}, 2000)
}
addCountAsync 这个方法 返回一个函数 这个函数接受两个参数 一个dispatch、一个getState, 我们改变状态的时候就通过dispatch触发就好了。
暂时就是这么多了,欢迎大家一起讨论。