First of All
Redux并不是全局state管理唯一的方案,基于开发不同的工程,我们可以选择三种方案来解决props传递的问题。
- Hook
- React Context API
- and Redux
store
store 是本地state的集合,操作的state的都在里面,本地state指的是组件及其子组件的state.
reducer
reducer干的事很简单, 拿到一个state
和一个action
返回 newstate
我们可以总结为一个arrow funciton:
1 | (state,action) => newState |
reducer 需要一个初始状态,并且我们需要确保reducer在任何状态下都有state,缺失state的reducer是非常差劲的写法,初始状态示意如下
1 | const initialState = { |
Dispatch Actions
现在我们有state了,需要一个function 来改变action, 这个funciton就叫dispatch, 而action则需要一个object来装。一般而言,只要有叫做type
的property就能叫做action。
1 | { |
Action描述的是你希望改变的state
而执行action的动作叫做dispatch
Dispatch 的运行机制
dispatch可以在store对象上运行,比如
1 | store.dispatch({type:"Do Something"}) |
但我们需要注意到,实际上每一次store run dispatch 都是在调用 re’ducer
那么话题就回到reducer上了,我们需要在reducer里handle被dispatch的action
我们可以采用比较ugly的风格,比如
1 | if(action === "do things 1"){ |
也可以采用比较好看一点的switch case
来完成action的处理。
我们可以注意到,reducer承担的职责更多了,同时也会导致reducer函数的复杂化。那么就引出了话题,我们应该如何写reducer函数。
Reducer的注意事项
根据规则的推荐,reducer首先需要是一个无副作用的纯函数。
这就意味着我们不能 随便的碰state
这个重要的参数
错误的示范如下
1 | state.something = 0; |
那么如何正确的更新state?
我们需要跟随如下规则
- State是只读的,只有action能更改他
- 更新的唯一方式是
dispatch(action)->reducer->newState
- Reducer函数必须是无副作用的纯函数,即不能修改他的参数
连接组件与Store
现在我们需要把组件和store连接起来,使这个下所有的子组件都可以访问store.做法如下,我们需要引入一个组件叫做Provider
1 | import { Provider } from 'react-redux'; |
这样,childcomponent 以及 childcomponent的子component都可以正常访问store了
Provider是使用React-Context实现的,比起context他看起来更加友好和易于理解。
在子组件中连接Redux
我们首先需要在子组件中引入connect
组件。
1 | import { connect } from 'react-redux'; |
此外需要注意的是,connect是高阶函数或者叫高阶组件 ,他的作用是拿到一个传入参数是函数的时候,返回一个函数,在这个情境下,则是传入一个组件,返回一个新的组件。
至于 mapStateToProps只是一个便于理解的名称,它可以叫任何东西,以及,他只要接受state
对象然后返回props
对象
我们其实知道react在组件中传递到的都是props
而mapsStateToProps这个function实际的作用是
- 将需要传递的states map 成 props的形式进行传递
- 筛选需要传递的states
向子组件中传递Dispatch Actions
现在我们的子组件已经能读取到他需要的父组件的state了,我们还需要传递dispatch actions让他能够使用,在子组件里,我们只要添加
1 | this.props.dispatch({type:"DoSomething"}); |
就可以正常使用dispatch actions了
另外,我们完全可以将actions放进名为action.js
的文件里
并将我们的actions进行输出
1 | export const DoSomething = "DoSomething" |
更进一步,当我们面对整个项目越来越复杂的actions的时候,action.js,或者叫action生成器将帮助我们走出困境。
正确的使用ACTION生成器
我们可以如此正确的使用action.js,除了上文提到的赋值const,我们还可以将action.,js
1 | export const DoSomething = "DoSomething" |
使用Redux 请求数据
1 |