我正在React中创建一个游戏,该游戏也使用Google Firestore来跟踪游戏数据。
在游戏中,用户将点击“开始”并连接到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来演示此问题。当您单击按钮时,“点击数”不会增加。
什么是使函数在调用时而不是在创建时引用组件的state
的好方法?
答案 0 :(得分:0)
使用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);
};
这应该可以回答您的问题,但是可以用比这更好的方法来解决您的问题。