专栏名称: xiaoT
前端开发
目录
相关文章推荐
51好读  ›  专栏  ›  xiaoT

2020 年 React 状态管理

xiaoT  · 掘金  ·  · 2020-04-06 16:07

正文

阅读 7

2020 年 React 状态管理

原文地址: 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 = ()






请到「今天看啥」查看全文