applyMiddlewrae
要为 dispatch
创建一个闭包?combineReducers
调用其所有 reducer 时,为什么不引入第三个参数来表示整个 state?mapDispatchToProps
中不允许使用 getState()
或 mapStateToProps()
的返回值?订阅者(subscribers)的意图是响应 state,而不是 action。对 state 的更新是同步的,但给订阅者的通知可能是批处理(batched)或节流(debounced)的,也就是说每次 action 发出时,订阅者不一定立刻得到通知。这是一种常见的避免重复渲染所做的 性能优化。
使用 enhancer 来替换 store.dispatch
是可以覆盖批处理或节流行为的,从而改变通知订阅者的方式。同时,有些类库可以让 Redux 成批处理 action 来优化性能的同时避免重复渲染:
store.dispatch()
传递一个由 action 组成的数组,包含的这些 action 只发送一个通知。这是为了保证 Redux 最终调用所有订阅者时使用最新的 state,但并非在每次 action 发出后调用所有订阅者。在订阅者中你很容易得到 store 当前的 state,只需调用 store.getState()
就行了。而在订阅者中你却没法得到 action,因为多个 action 可能会被成批处理。
在订阅者中使用 action 有一种可能的使用场景(当然这个特性并不支持),就是为了保证组件只在特定 action 发出后重新渲染。而对于重新渲染的控制应使用以下方法代替:
文章
讨论
Redux 使用函数(称为 action 创建函数)来返回一个 action 对象的模式,在某些有着丰富面向对象开发经验的程序员眼中,似乎显得有悖常理。他们觉得这是这显然是类(class)和实例(instance)的使用场景。然而 Redux 不支持类的实例作为 action 对象和函数,这是因为类的实例会使得序列化(serialization)和反序列化(serialization)这样的工作更加棘手。如 JSON.parse(string)
这样的反序列化方法返回的是一个普通 JavaScript 对象而不是一个类的实例。
正如 组织 State 所描述的那样,如果你不需要像数据持久化、时间旅行调试这样的功能,那么完全欢迎把不可以序列化的数据放入 Redux 的 Store 中存储。
序列化可使浏览器使用更少的内存,储存之前所有被 dispatch 的 action,以及 store 中所有以前的 state。时间回溯和“热加载”是提升 Redux 开发者开发体验的核心,也是 Redux Devtools 的功能所在。而且在 Redux 服务端渲染的场景中,可以把已经序列化的 action 储存在服务器,然后在浏览器中重新序列化。
文章
讨论
有些人认为使用 [柯里化函数签名] 的方式声明 middleware 是 没有必要的 ,因为当 applyMiddleware 函数执行时 store 和 next 都是存在的。这个 issue 已经被认为是 不值得为此引入破坏性修改。
讨论
applyMiddleware
要为 dispatch
创建一个闭包?applyMiddleware
从 store 中获取已有的 dispatch,然后把它封装在一个闭包中来创建最开始的 middleware 链。然后用一个对象调用来调用,以暴露出 getState 和 dispatch 函数。这样做可以使得 middleware 在初始化时可以使用 dispatch。
讨论
combineReducers
调用其所有 reducer 时,为什么不引入第三个参数来表示整个 state?combienReducer
鼓励你按照“域”(domain)来划分 reducer 逻辑。正如 combineReducers
进阶 所说,combineReducers
被有意限制于单一的应用场景:把不同片段的 state 的更新工作委托给一个特定的 reducer,以此更新由普通的 JavaScript 对象构成的 state 树。
对于每一个 reducer 来说,潜在的第三个参数应该是什么并不那么确定:可以是整个 state 树、可以是某些回调函数、可以是 state 树的其它部分、等等。如果 combineReducers
不符合你的使用场景,可以考虑使用其它的库,比如 combineSectionReducers 或 reduceReducers,来获取更多选项:诸如深层嵌套的 reducer 或能够获取到全局 state 的 reducer。
如果这些发布的工具都解决不了你的使用场景,你总是可以自行实现一个函数来精确地实现你的需求。
文章
讨论
mapDispatchToProps
中不允许使用 getState()
或 mapStateToProps()
的返回值?曾经有人希望在 mapDispatch
中使用整个 state
或 mapState
的返回值,这样一来 mapDispatch
中声明的函数就能拿到 store
中最新的返回值了。
然而 mapDispatch
并不支持这种做法,因为这么做意味着每次 store 更新后 mapDispatch
也需要被调用,导致每次 state 更新后函数需要重新创建,从而带来很多性能开销。
像这种“需要基于当前 state 以及 mapDispatchToProps 函数来替换 prop”的场景,正确的处理方式是使用 mergeProps(connect 函数的第三个参数)。如果这个参数被定义,它会被传入 mapStateToProps()
和 mapDispatchToProps()
的结果、以及容器组件的 prop。而 mergeProps
返回的普通对象(plain object)会作为 prop 传入包装的组件(wrapped component)。
讨论