想要展示如何在 React 元件之間共享任何可序列化的數據,例如NextJS 中的客戶端元件。
我們有一些不相關的組件:
讓我們建立一個包含初始狀態的物件
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>
你可以在這裡看到它是如何運作的 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中文網其他相關文章!