javascript - React SetState is ignored
问题描述
I'm trying to make a timer that starts at 1.0 and increases 0.1 until it reaches a random number. You have to start a "session" 5 seconds after the component is rendered and this is all working. The problem is that I want a session to start 5 seconds after another finishes and React ignores the setState that would allow those next sessions and i dont understand why.
Note: It only works if I create a button that calls a toggle function with
setIsGameActive(isGameActive => isGameActive = !isGameActive)
and click it
const GamePanel = () => {
const [gameTime, setGameTime] = useState(1);
const [isGameActive, setIsGameActive] = useState(false);
const [gameEndTime, setGameEndTime] = useState(0);
const [lastResults, setLastResults] = useState([]);
let randomNumber = 0;
const useFirstTime = useRef({firstTime: true});
const makeRandomNumber = (min, max) => {
return min + (max - min) * Math.random()
}
const reset = () => {
setGameTime(1);
setIsGameActive(false); //ignored
}
const gameStart = () => {
if(useFirstTime.current.firstTime === false){
if(!isGameActive){
console.log("Game starting...");
randomNumber = makeRandomNumber(1.1, 5);
setGameEndTime(randomNumber.toFixed(1))
setIsGameActive(true);
}
}
}
const gameFinished = () => {
setTimeout(()=>{
reset();
gameStart()
}, 5000)
}
useEffect(() => {
if(useFirstTime.current.firstTime === true){
useFirstTime.current.firstTime = false;
setTimeout(() => {
gameStart();
}, 5000);
}
let interval = null;
if(isGameActive){
interval = setInterval(() => {
if(gameTime.toFixed(1) !== gameEndTime){
setGameTime(gameTime => gameTime + 0.1)
}
if(gameTime.toFixed(1) === gameEndTime){
clearInterval(interval)
gameFinished();
}
}, 100);
}else if(!isGameActive && gameTime !== 0){
clearInterval(interval)
}
return () => clearInterval(interval);
}, [isGameActive, gameTime, gameEndTime, gameStart, gameFinished]);
return(
<section id="game-panel">
<h1></h1>
<h1>{gameTime.toFixed(1)}x</h1>
</section>
);
}
export default GamePanel;
Thanks!!
解决方案
The reset function is created everytime your Component is rendered. Because of this the reset reference inside the timer is different than in the component itself after rerendering. Try to use useCallback
for reset to create a memorized version of the function: https://reactjs.org/docs/hooks-reference.html#usecallback
const reset = useCallback(() => {
setGameTime(1);
setIsGameActive(false); //ignored
},[])
推荐阅读
- jquery - jQuery。scrollPercent - 向左更改 + 动画后
- java - 如何不仅从根级别获取属性
- java - 如何在 Spring Boot 中验证 JSON 请求?
- r - 如何根据我选择的列在 rshiny 中绘图
- javascript - 如何使用javascript文件解码编码?
- javascript - 无法附加到节点
- azure-devops - VSTS 部署 Service Fabric 应用程序任务:压缩包设置失败
- mysql - 为什么 MySQL 总是在“JOIN”列索引上选择“is NULL”列索引?
- python - 从内部类引用父对象实例
- logstash - 如何设置 Logstash JDBC 输出以写入 JSON 字段?