原文地址: medium.com/better-prog…
译文地址:github.com/xiao-T/note…
本文版权归原作者所有,翻译仅用于学习。
我们是否还需要 Redux 和 Mobx 这类的状态管理框架?
引言
React hooks 的引入无疑改变的了 state 管理的现状。
在此之前,很难在组件之间共享 state 相关的逻辑。现在,我们可以很简单的通过抽象一个 hook 来处理(例如:useUserLogin)。
这就引出了问题,为什么我们还需要状态管理框架?在这篇文章中,我将展示我的决策过程:如何管理 state。关于在2020年我们是否还需要 state 管理框架,我也会分享我的观点。
有什么变化?
在有 Hooks 之前,我们是如何定义 state 的?基本上,有两种选择:在组件内部定义本地 state,或者用一个 state 管理框架设置全局的 state (例如:Mobx/Redux)。
本地 state (hooks 之前)
export class UserList extends Component {
state = {
isLoading: false,
hasError: false,
users: []
}
searchUsers(value) {
this.setState({isLoading: true});
api.get(`/users?searchKey=${value}`)
.then((data) => this.setState({users: data}))
.catch(() => this.setState({hasError: true}))
.finally(() => this.setState({loading: false}));
}
render() {
if (this.state.isLoading) {
// render loading spinner
}
if (this.state.hasError) {
// render error message
}
return (
<div>
<input onChange={(event) => this.searchUsers(event.target.value)} />
</div>
)
}
}
在接下来我们会说明只有这两个选择时带来的问题。假设,我们的 state 不必设为全局,但是,我们希望可以在多个组件复用 state,我们该如何定义本地 state。
在上面的演示中,我们或许想复用 loading 和 error state,在 Hooks 之前,是不可能的。唯一的选择是需要利用 Redux 来复用它。在 Redux 中,任何需要搜索用户的组件只需简单 dispatch 一个 action(searchUsers())和监听全局 state 的变化即可。
然而,使用这些全局 state(Redux/Mobx)会带来一些问题:
- 更多的样板代码
- 复杂的数据流
- 多个组件同时维护全局 state,这可以能会带来意想不到的副作用。
解决方案:React Hooks!
谢天谢地 React v16.8 引入的 Hooks。从这时起,在做组件之间共享 state 相关的逻辑变得可行。
在下面的演示中,我们可以共享 loading 和 error 的行为:
import {useState} from 'react';
const useRequestHandler = () => {
const [isLoading, setLoading] = useState(false);
const [hasError, setError] = useState(false);
const [data, setData] = useState(null);
const handleRequest = (request) => {
setLoading(true);
setError(false);
return api.get(request)
.then(setData)
.catch(() => setError(true))
.finally(() => setLoading(false))
};
return {isLoading, hasError, data, handleRequest};
};
const UserList = () => {
const {data, isLoading, hasError, handleRequest} = useRequestHandler();
const searchUsers = (value) => handleRequest(`/users?searchKey=${value}`);
return (
<React.Fragment>
{data.map(u => <p>{u.name}</p>)}
</React.Fragment>
)
}
更多好处:如果,多个组件需要搜索用户列表的功能,我们也可以自定义 useUserSearch hook。
然而,hooks 并不是银弹。把 state 保存在 hook 中,并不意味着它就变成了单例对象,它只是绑定在一个组件中。在某些情况下,我们只想保留一个实例 state 对象(例如:只加载一次用户信息)。这是 state 管理框架提供的功能。
如何,何时,何地管理 state
现在,可以在多个组件之间共享 state 相关逻辑了,那我们怎么决定 state 保存在组件内(本地),还是保存在 state 管理框架中(全局)呢?
下面的图片展示了我的决策过程。
State 管理框架有什么好处呢?
现在,我们知道如何在全局和本地做抉择了。但是,在2020年为什么还需要 state 管理框架呢?这相比 React Hooks 有什么好处呢?
有以下几个好处:
- 全局定义,也代表只有一个实例对象
- 只会加载一次远程数据
- 开发工具的支持
- 为软件工程师提供了一种标准的开发方式
总结
我们看到 React Hooks 已经搅动了 state 管理的格局。由于它们的引入,在组件之间共享 state 相关逻辑变得更加简单。
然而,Hooks 并不是银弹,我们仍旧需要 state 管理框架。这也并不是说要让所有的 state 都是全局的 — 大多情况下让其保留在组件之间更加好。只有在有绝对必要的情况下,才把 state 移动到 state 管理框架中。