2020 年 React 状态管理

原文地址: medium.com/better-prog…
译文地址:github.com/xiao-T/note…
本文版权归原做者全部,翻译仅用于学习。react


咱们是否还须要 Redux 和 Mobx 这类的状态管理框架?git

引言

React hooks 的引入无疑改变的了 state 管理的现状。github

在此以前,很难在组件之间共享 state 相关的逻辑。如今,咱们能够很简单的经过抽象一个 hook 来处理(例如:useUserLogin)。api

这就引出了问题,为何咱们还须要状态管理框架?在这篇文章中,我将展现个人决策过程:如何管理 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)会带来一些问题:this

  • 更多的样板代码
  • 复杂的数据流
  • 多个组件同时维护全局 state,这能够能会带来意想不到的反作用。

解决方案:React Hooks!

谢天谢地 React v16.8 引入的 Hooks。从这时起,在作组件之间共享 state 相关的逻辑变得可行。spa

在下面的演示中,咱们能够共享 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 管理框架中。

相关文章
相关标签/搜索