如何避免 React 功能组件中的陈旧状态

How to avoid stale state in React functional component

我正在用 React 创建一个游戏,它也使用 Google Firestore 来跟踪游戏数据。

在游戏中,用户将点击 "Start" 并连接到 Google Firebase 集合,该集合开始监听数据库的变化。当数据库中的某些内容发生变化时,React 组件状态将发生变化。

我遇到的问题是 state 我的侦听器回调函数使用的版本似乎已过时。监听器是为响应玩家点击开始按钮而设置的,当时组件的 state 似乎被缓存了。

有问题的组件如下所示:

import React, { useEffect, useState } from "react";

function Counter() {
  const [state, setFullState] = useState({
    count: 0,
    clicks: 0,
    started: false
  });

  const setState = update => {
    setFullState(prevState => {
      return {
        ...prevState,
        ...update
      };
    });
  };

  const handleStart = () => {
    const increment = () => {
      const { clicks } = state;
      setState({ clicks: clicks + 1 });
    };
    setState({
      started: true
    });
    document.addEventListener("click", increment);
  };

  const { clicks, count, started } = state;

  if (!started) {
    return (
      <div>
        <button onClick={handleStart}>START</button>
      </div>
    );
  }

  return (
    <div>
      <h2>Hooks</h2>
      <p>Count: {count}</p>
      <p>Clicks: {clicks}</p>
      <p>
        <button
          onClick={() => {
            setState({ count: count + 1 });
          }}
        >
          More
        </button>
      </p>
    </div>
  );
}

export default Counter;

我创建了一个 sandbox 来演示这个问题。单击按钮时,"Clicks" 数字不会增加。

在函数 调用 时,而不是在函数 [=27] 时,使函数引用组件 state 的好方法是什么? =]创建?

使用 useRef 您可以在现在过时的 increment 回调中保持状态快照可见,并保持同步。

const currentState = React.useRef(state)
currentState.current = state

然后

  const handleStart = () => {
    const increment = () => {
      const { clicks } = currentState.current;
      setState({ clicks: clicks + 1 });
    };
    setState({
      started: true
    });
    document.addEventListener("click", increment);
  };

这应该可以回答您的问题,但您的问题可以用比这更好的方法解决。