React组件Props更新异常:GameState组件Props始终滞后一轮
问题解决:子组件状态更新后父组件接收值滞后一轮
问题现象
通过GameInfo组件的下拉框切换难度后,GameState组件显示的difficulty属性值始终比实际选中的难度配置滞后一轮——比如选中「Normal」难度时,GameState仍显示「Easy」的7秒,再次切换到「Hard」时才显示「Normal」的5秒,该问题可通过控制台日志及界面演示复现。
问题根源
React的useState状态更新是异步的。在GameInfo组件的changeDifficultyHandler函数中,调用setDifficulty(levels[event.target.value])后立刻使用当前的difficulty状态传递给父组件,此时difficulty还未完成更新,传递的仍是更新前的旧值,导致父组件的currentDifficulty状态滞后,最终GameState拿到的props也跟着滞后。
解决方案
有两种可行的修复方式:
方案1:直接传递选中的最新难度值
不需要依赖组件内部的difficulty状态,直接将选中的levels[event.target.value]传给父组件:
const changeDifficultyHandler = (event) => { const selectedDifficulty = levels[event.target.value]; setDifficulty(selectedDifficulty); props.onChangeDifficulty(selectedDifficulty); };
方案2:使用useEffect监听状态变化
通过useEffect监听difficulty状态的更新,当状态变化时再通知父组件:
import { useState, useEffect } from 'react'; const GameInfo = (props) => { // ... 其他代码不变 useEffect(() => { props.onChangeDifficulty(difficulty); }, [difficulty, props.onChangeDifficulty]); const changeDifficultyHandler = (event) => { setDifficulty(levels[event.target.value]); }; // ... 其他代码不变 };
代码修改示例(方案1)
修改后的GameInfo组件代码:
import { useState } from 'react'; const GameInfo = (props) => { const levels = { Easy: { time: 7, wordCount: 15, }, Normal: { time: 5, wordCount: 25, }, Hard: { time: 3, wordCount: 30, }, }; const [difficulty, setDifficulty] = useState(levels.Easy); const changeDifficultyHandler = (event) => { const selectedLevel = levels[event.target.value]; setDifficulty(selectedLevel); props.onChangeDifficulty(selectedLevel); }; return ( <div> You Are Playing On The{' '} <span> [ <select onChange={changeDifficultyHandler}> <option value='Easy'>Easy</option> <option value='Normal'>Normal</option> <option value='Hard'>Hard</option> </select> ] </span>{' '} Difficulty & You Have{' '} <span className='text-main font-poppins font-bold'> [ {difficulty.time} ] </span>{' '} Seconds To Type The Word. </div> ); }; export default GameInfo;
内容的提问来源于stack exchange,提问作者Amir Adel
相关产品推荐
相关产品推荐

