首页  >  文章  >  web前端  >  在不相关的 React 组件之间共享状态

在不相关的 React 组件之间共享状态

WBOY
WBOY原创
2024-07-17 06:51:301134浏览

想要展示如何在 React 组件之间共享任何可序列化的数据,例如NextJS 中的客户端组件。

我们有一些不相关的组件:

Example app UI

让我们创建一个包含初始状态的对象

export const state: { count: number } = { count: 0 };

我们可以将数据存储在 Map 或 WeakMap 中,状态将是访问它的键。另外,还需要一个订阅者数组。

const stateMap = new WeakMap<object, object>();
const subscribers: (() => void)[] = [];

现在让我们编写一个钩子来订阅数据更改。

export function useCommonState<T extends object>(stateObj: T) {
  // more efficient than `useEffect` since we don't have any deps
  React.useInsertionEffect(() => {
    const cb = () => {
      const val = stateMap.get(stateObj);
      _setState(val!);
    };
    // subscribe to events
    subscribers.push(cb);

    return () => {
      subscribers.slice(subscribers.indexOf(cb), 1);
    };
  }, []);
}

现在让我们添加与获取和设置状态相关的逻辑

  // all instances of hook will point to same object reference
  const [state, _setState] = React.useState<typeof stateObj>(() => {
    const val = stateMap.get(stateObj) as T;
    if (!val) {
      stateMap.set(stateObj, stateObj)
      return stateObj
    }
    return val
  });

  const setState = React.useCallback((newVal: object) => {
    // update value
    stateMap.set(stateObj, newVal);
    // notify all other hook instances
    subscribers.forEach((sub) => sub());
  }, []);

  return { state, setState };

现在可以在 3 个组件中使用它,例如

import { state as myState } from './state';
//...

const { state, setState } = useCommonState(myState);

<button
  onClick={() => setState({ count: state.count + 1 })}
  className="p-2 border"
>
  +
</button>
// ...
Component A<div>Count: {state.count}</div>

Final app

你可以在这里看到它是如何工作的 https://stackblitz.com/~/github.com/asmyshlyaev177/react-common-state-example
或者在这里 https://codesandbox.io/p/github/asmyshlyaev177/react-common-state-example/main
或者在github https://github.com/asmyshlyaev177/react-common-state-example

查看我基于此原则的 NextJS 库 https://github.com/asmyshlyaev177/state-in-url

Tnx 阅读。

以上是在不相关的 React 组件之间共享状态的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn