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

Reactjs 如何避免React功能组件中的陈旧状态,reactjs,Reactjs,我正在React中创建一个游戏,它还使用Google Firestore来跟踪游戏数据 在游戏中,用户将点击“开始”,并连接到Google Firebase集合,该集合开始监听数据库的更改。当数据库中的某些内容更改时,React组件状态将更改 我遇到的问题是,我的侦听器回调函数使用的state版本似乎已经过时。侦听器是根据播放器点击开始按钮而设置的,此时组件的状态似乎被缓存 有问题的组件如下所示: import React, { useEffect, useState } from "react

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

在游戏中,用户将点击“开始”,并连接到Google Firebase集合,该集合开始监听数据库的更改。当数据库中的某些内容更改时,React组件状态将更改

我遇到的问题是,我的侦听器回调函数使用的
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;
import React,{useffect,useState}来自“React”;
函数计数器(){
const[state,setFullState]=useState({
计数:0,
点击次数:0,
开始:错误
});
const setState=更新=>{
setFullState(prevState=>{
返回{
…国家,
…更新
};
});
};
常量handleStart=()=>{
常量增量=()=>{
const{clicks}=状态;
setState({clicks:clicks+1});
};
设定状态({
开始:对
});
文件。添加的列表器(“单击”,增量);
};
const{clicks,count,start}=状态;
如果(!已启动){
返回(
开始
);
}
返回(
钩子
计数:{Count}

点击:{Clicks}

{ setState({count:count+1}); }} > 更多

); } 导出默认计数器;
我创建了一个示例来演示这个问题。当你点击按钮时,“点击”次数不会增加


在调用函数时,而不是在创建函数时,使函数引用组件的
状态的好方法是什么

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

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


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

您想要什么还不清楚。您介绍了GoogleFirebase,但给出了一个使用
单击
侦听器的示例。关于您的示例,我可以告诉您的是,您必须仅在
useffect
钩子中添加侦听器,因为当您卸载组件时,您必须取消订阅事件。
setState
也必须被重新输入,否则它不会仅为巧合而工作,我认为在这种特定的情况下,这无关紧要:setFullState函数是稳定的,所以不管setState是否稳定。但是,是的,如果setState将来会做其他事情,比如读取state,也不会正常工作,
setFullState
是稳定的,因此可以用
setFullState(state=>({…state,clicks:state.clicks+1})代替refs来完成
@Federkun我用这个解决方案解决了这个问题,但你能指出什么是解决这个问题的“更好的方法”吗?这取决于你真正需要解决的问题。您可以使用
useReducer
并在侦听器中分派操作。或者只是``document.addEventListener(“单击“,()=>{setFullState((currentState)=>({…currentState,单击:currentState.clicks+1})));``,将最后一个增量回调保存到ref中,并调用它,等等。
  const handleStart = () => {
    const increment = () => {
      const { clicks } = currentState.current;
      setState({ clicks: clicks + 1 });
    };
    setState({
      started: true
    });
    document.addEventListener("click", increment);
  };