Hooks 状态管理订阅更新数据的 forceUpdate几种形式

1,892 阅读1分钟
实现一个React hooks基础状态管理

const createContainer = (initialState) => {
  let globalState = initialState;
  const listeners = Object.fromEntries(Object.keys(initialState).map(key => [key, new Set()]));

  const setGlobalState = (key, nextValue) => {
    if (typeof nextValue === 'function') {
      globalState = { ...globalState, [key]: nextValue(globalState[key]) };
    } else {
      globalState = { ...globalState, [key]: nextValue };
    }
    listeners[key].forEach(listener => listener());
  };

  const useGlobalState = (key) => {
    const [state, setState] = useState(globalState[key]);
    useEffect(() => {
      const listener = () => {
        setState(globalState[key]);
      };
      listeners[key].add(listener);
      listener(); // in case it's already changed
      return () => { listeners[key].delete(listener) }; // cleanup
    }, []);
    return [state, (nextValue) => setGlobalState(key, nextValue)];
  };

  return {
    setGlobalState,
    useGlobalState,
  };
};
上述的 forceUpdate 为

const useGlobalState = (key) => {
    const [state, setState] = useState(globalState[key]);
    useEffect(() => {
      const listener = () => {
        setState(globalState[key]);
      };
      listeners[key].add(listener);
      listener(); // in case it's already changed
      return () => { listeners[key].delete(listener) }; // cleanup
    }, []);
    return [state, (nextValue) => setGlobalState(key, nextValue)];
  };
我们可以利用对象的不想等性质改写forceUpdate 为另外一种形式

const useGlobalState = (key) => {
  const [, forceUpdate] = useState({});
  useEffect(() => {
    const listener = () => {
      forceUpdate({});
    };
    listeners[key].add(listener);
    listener(); // in case it's already changed
    return () => { listeners[key].delete(listener) }; // cleanup
  }, []);
  return [globalState[key], (nextValue) => setGlobalState(key, nextValue)];
};
我们可以利用自增数值改写forceUpdate 为另外一种形式

const useGlobalState = (key) => {
  const [, forceUpdate] = useState(0);
  useEffect(() => {
    const listener = () => {
      forceUpdate(c => c + 1);
    };
    listeners[key].add(listener);
    listener(); // in case it's already changed
    return () => { listeners[key].delete(listener) }; // cleanup
  }, []);
  return [globalState[key], (nextValue) => setGlobalState(key, nextValue)];
};