返回

基于 React Context Api 和 Es6 Proxy 的状态管理方案

前端

在近几个月的工作中,我遇到了一些场景:项目基本不需要全局的状态管理,但页面级的状态管理肯定需要在一些组件中共享。引入 Redux 等状态管理库会显得繁琐,而直接通过 props 传递,又觉得写起来不是那么优雅。刚好项目中 React 版本比较新,就试用了下 Context Api,代码大致如下:

import React, { createContext, useContext } from "react";

const Context = createContext(null);

const Provider = ({ children, value }) => {
  return <Context.Provider value={value}>{children}</Context.Provider>;
};

const useGlobalState = () => {
  return useContext(Context);
};

export { Provider, useGlobalState };

然后,在需要共享数据的组件中,可以使用 useGlobalState 钩子来获取共享数据。例如:

import { useGlobalState } from "./context";

const MyComponent = () => {
  const { count } = useGlobalState();

  return <div>{count}</div>;
};

这个例子中,MyComponent 组件通过 useGlobalState 钩子获取了共享数据 count,并将其渲染到页面上。

Context Api 的这种方式可以很好地实现组件之间的状态共享,但也有一个缺点,就是当共享数据发生变化时,所有使用该数据的组件都会重新渲染。为了解决这个问题,我们可以使用 Es6 Proxy 来对共享数据进行代理,从而避免不必要的重新渲染。

我们可以创建一个代理对象,并将其作为 Context Api 的值。当共享数据发生变化时,代理对象会自动更新,但只有使用该数据的组件才会重新渲染。

import React, { createContext, useContext } from "react";

const Context = createContext(null);

const Provider = ({ children, value }) => {
  const proxy = new Proxy(value, {
    set: (target, property, value) => {
      target[property] = value;
      Context._currentValue = value;
      return true;
    },
  });

  Context._currentValue = value;

  return <Context.Provider value={proxy}>{children}</Context.Provider>;
};

const useGlobalState = () => {
  return useContext(Context) || Context._currentValue;
};

export { Provider, useGlobalState };

这个代理对象会自动跟踪共享数据的变化,并仅更新使用该数据的组件。这样就可以避免不必要的重新渲染,提高应用程序的性能。

Context Api 和 Es6 Proxy 相结合,可以为小型到中型的 React 项目提供一个简单、高效的状态管理方案。代码实例丰富,便于理解。如果您正在寻找一种轻量级的状态管理方案,可以考虑使用这种方法。