- LifeCycle
- 1. 调用`store.dispatch(action)`
- 2. Reducer接收Action
- 3. Root Reducer会将所有sub reducer的结果给结合起来并返回
- 4. Redux会保存最后结合起来了的State并且调用各个监听器
- Key Concepts
- Reducer
- 关于多个同级Reducer
- Store
个人笔记, 基于官方英文教程, 添加了一些批注, 有一些单词翻译起来真困难
Redux 基于严格单向数据流实现 反正就是为了打破 React 自身的数据流而创建的
LifeCycle
1. 调用store.dispatch(action)
- 可以在任何地方调用这个函数,只要引用 store 进来就可以了.
- 甚至可以在 AJAX callback 中, 或者 setInterval 里面调用
action 的格式如下:
代码语言:javascript复制{ type: 'LIKE_ARTICLE', articleId: 42 }
{ type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'Mary' } }
{ type: 'ADD_TODO', text: 'Read the Redux docs.' }
通过这个
action
对于用户操作的描述可以变得非常的具象
2. Reducer 接收 Action
默认会提交两个参数给 Reducer:
- 当前 State
- 第一步提供给
dispatcher
的参数action
3. Root Reducer 会将所有 sub reducer 的结果给结合起来并返回
参考下文提到的
combineReducers()
的使用示例
4. Redux 会保存最后结合起来了的 State 并且调用各个监听器
现在这个时候已经获取到了下一个状态了
如果我使用store.subscribe(listener)
注册了个监听器,会在这个时候被调用,并且可以通过store.getState()
获取到当前的状态
最后通过更新之后的状态刷新 UI
Key Concepts
- 使用 Pure Function 来描述 State 变化
- 即通过各种 Dispatcher 将状态变化的请求提交给 reducer 来处理, reducer 仅仅返回下一个状态
pure function: 可以根据传入的值预测结果,并且不会影响其他值, 即不改变传入的值也不会创建闭包
- 因为 reducer 是一个 pure function, 里面不应该对任何状态进行修改
- 所有的状态变化通过一个大的 Dispatcher 进行分发
- 因此所有的状态变化都应该提交到这个 Dispatcher 上面, 这样就不会出现不同层次的混乱的数据流了
Reducer
基本格式:
代码语言:javascript复制(previousState, action) => newState
必须满足以下几点:
- 不能够修改传入的值
- 不应该提交额外的 API/Http 请求
- 调用一些 non-pure function, 比如
Date.now()
或者Math.random()
(这些函数的结果无法预料) - 可以根据传入的参数,确定传回来的值
一个详细一点的例子:
代码语言:javascript复制export default (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
- 会根据会根据传入的
action
的类型进行不同的处理 - 另外
action
不一定要字符串,可以传更多类型,甚至可以传一个 obj 进来 - 记住一定要返回新的状态, 一定要覆盖到所有的情况
关于多个同级 Reducer
可以通过combineReducers
函数返回多个 sub-Reducer, 例如上面返回了a
和b
两个 reducer
import { combineReducers } from 'redux'
const a = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state 1
default:
return state
}
}
const b = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state 2
default:
return state
}
}
const e = combineReducers({
a,
b
})
export default e
如果我们在 reducer 里面提供了多个函数 那么当我们分发一个特定动作的时候, 比如
代码语言:javascript复制console.log( store.dispatch({type: 'INCREMENT'}) )
这个动作就会提交到所有的函数之上, 也就是说, 上方a
会接收这个动作,b
也会接受这个动作,然后以下面的格式进行返回:
{
a: 1, //经过 a 处理之后的状态
b: 2 //经过 b 处理之后的状态
}
类似于用参数{state, action}便利并执行了整个 reducer 里面所有 reducer 函数
Store
用于分发 Action 到 Reducers, 他需要做这样的操作
- 获取这个应用的状态
- 可以通过
getState()
获取到状态 - 可以通过
dispatch(action)
来分发动作 - 可以通过
subscribe(listener)
来注册监听器
- 并且还要通过
subscribe(listener)
的返回值决定是否接触监听器
创建 Store 的例子:
代码语言:javascript复制import { createStore } from 'redux'
import todoApp from './reducers'
const store = createStore(todoApp)