【问题标题】:Latest state is not reflected after dispatch until next render派发后直到下一次渲染才反映最新状态
【发布时间】:2020-05-01 17:35:03
【问题描述】:

我在 React 状态管理方面遇到了问题。 我想在单击按钮后使用 Context API 更新全局状态,然后使用更新后的状态执行其他操作。

按钮将动作分派到全局状态。但是,当我尝试在之后立即读取状态时,更改不会反映,直到应用重新渲染。

const App = () => {
  const playerRef = useRef();
  const { state, addPlayers } = useContext(playerContext);

  // subscribe playerRef changes to global state,
  useEffect(() => {
    playerRef.current = state;
    console.log("players #", playerRef.current.length);
  }, [state]);

  const add = useCallback(() => {
    // dispatch an add players action to the store
    addPlayers([{ name: "new" }, { name: "newer" }]);

    // PROBLEM: Need latest state value here after dispatch
    // but it's not immediately reflected here
    console.log("player # after dispatch ", playerRef.current.length);

    // do something with the new state
  }, [playerRef, addPlayers]);

  const handleSubmit = () => {
    add();
  };

  return (
    <div>
      <p>Players: {String(state.map(player => player.name))}</p>
      <button type="button" onClick={handleSubmit}>
        AddPlayers
      </button>
    </div>
  );
};

export default App;

这是控制台显示的内容。

link 到代码框查看完整的应用程序。 谢谢。

【问题讨论】:

    标签: reactjs state react-context


    【解决方案1】:

    您正试图在状态更新后立即读取 playerRef.current 的值:

      const add = useCallback(() => {
        addPlayers([{ name: "new" }, { name: "newer" }]);
        console.log("player # after dispatch ", playerRef.current.length);
      }, [playerRef, addPlayers]);
    

    但是,playerRef.current 的值在运行以下效果之前不会更新:

      useEffect(() => {
        playerRef.current = state;
        console.log("players #", playerRef.current.length);
      }, [state]);
    

    useCallback 通话结束后最快会发生这种情况*

    您应该改为读取state 的值。 Refs 应该用作实例变量来捕获稍后要读取的值;这对他们来说不是一个很好的用例。您试图做的基本上是这样的:

      const { state, addPlayers } = useContext(playerContext);
      const playerRef = React.useRef();
      playerRef.current = state;
    

    也可能是:

      const { state: currentPlayer, addPlayers } = useContext(playerContext);
    

    * 这可能不太准确,但无论哪种方式,您都 这样做取决于竞争条件。

    【讨论】:

      猜你喜欢
      • 2013-02-21
      • 2022-06-28
      • 2021-10-15
      • 1970-01-01
      • 2020-01-13
      • 2021-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多