原文:useReducer, don't useStatehtml
本文难度:入门级别前端
本文默认你已经大概了解过 React Hooks,若是不了解能够先看看 ReactJS 的文档。react
当开发者们开始在他们的应用中使用 React Hooks API 时,不少人一开始都会把 useState 做为他们的状态管理工具。 然而,我强烈认为 useReducer 比 useState 更适合作状态管理。函数
首先我来定义一下『更适合』是什么意思:工具
接下来我分别对三点进行阐述。测试
这篇文章大部分观点只是个人主观见解。spa
useState 有一个与 class 组件里面的 setState 明显不一样的地方,那就是 useState 不对状态作浅层合并了,而 useReducer 会合并。code
为了说明这一点,我这里给一个使用 useReducer 来实现『撤销/重作』的例子:htm
function init(initialState) {
return {
past: [],
present: initialState,
future: [],
}
}
function reducer(state, action) {
const { past, future, present } = state
switch (action.type) {
case 'UNDO':
const previous = past[past.length - 1]
const newPast = past.slice(0, past.length - 1)
return {
past: newPast,
present: previous,
future: [present, ...future],
}
case 'REDO':
const next = future[0]
const newFuture = future.slice(1)
return {
past: [...past, present],
present: next,
future: newFuture,
}
default:
return state
}
}
复制代码
用 useState 达到相同的效果有点困难,不过也并非不可能。我只是想告诉里使用 useReducer 是多么地方便,这也引出了第二点。blog
译注:若是用 useState 来作,只须要把 past / present / future 放到同一个 state 里面便可,可是会形成代码分散。并且 useState 也不推荐你在一个 state 里放太多东西,由于它不会合并 state,用起来不方便。
在 Web 开发中,咱们面对的问题不少时候并非纯技术问题。大部分时候你都要跟其余开发者工做,他们的开发经验极可能跟你的很不同。
因为大部分前端开发者都了解过 Redux,因此使用 useReducer 比使用 useState 更能快速得到收益。其核心概念好比 diapatch 一个 action,使用 reducer 来更新 state,都比 useState 更容易被这些开发者掌握。
还有一点值得注意,那就是即便你目前是一我的在开发一个应用,你也保不齐之后会有其余人接手这份代码。
要论 Hooks RFC、Twitter 里被讨论最多的话题,那就是如何测试 Hooks。我以为要让开发者理解测试 Hooks 的最佳实践,仍是要花费一些时间的(译注:尤为是 useState)。可是若是你使用的是 useReducer,那么你全部的跟 state 相关的业务逻辑代码均可以放到一个单独的函数里,跟你的组件分开,很是好测试。
把状态更新代码和渲染逻辑分开,使得你能够把测试代码也分红这两部分。以上面的 reducer 代码为例, 咱们能够轻松地测试撤销和重作,作法是把 mock 状态和 action 传给 reducer 便可,咱们甚至不用引入 React!
test('it supports undoing the state', () => {
const state = { past: [{ count: 0 }], present: { count: 1 }, future: [] }
const newState = reducer(state, { type: 'UNDO' })
expect(newState.present.count).toBe(0)
})
复制代码
我并不指望你们只使用 useReducer 不使用 useState,我我的也不会这么作,它们各有各的使用场景。可是个人确认为 useReducer 在复杂的状态管理场景下比 useState 更好维护。