原创文,最初发布于 szhshp的第三边境研究所 , 转载请注明
个人笔记, 基于官方英文教程, 添加了一些批注, 有一些单词翻译起来真困难
Redux基于严格单向数据流实现
反正就是为了打破React自身的数据流而创建的
LifeCycle
1. 调用store.dispatch(action)
- 可以在任何地方调用这个函数,只要引用store进来就可以了.
- 甚至可以在AJAX callback中, 或者setInterval里面调用
action的格式如下:
{ 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
基本格式:
(previousState, action) => newState
必须满足以下几点:
- 不能够修改传入的值
- 不应该提交额外的API/Http请求
- 调用一些non-pure function, 比如
Date.now()
或者Math.random()
(这些函数的结果无法预料) - 可以根据传入的参数,确定传回来的值
一个详细一点的例子:
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里面提供了多个函数
那么当我们分发一个特定动作的时候, 比如
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的例子:
import { createStore } from 'redux'
import todoApp from './reducers'
const store = createStore(todoApp)