React猜字游戏重置按钮需点击两次才生效,组件不及时重渲染
问题原因与解决方案
问题出在React状态更新的异步性:你在resetGame中调用setNumberInList后,numberInList并不会立即更新为新值。紧接着执行的setGeneratedWord(randomWordsList[numberInList])和setGeneratedWordLetters依赖的都是更新前的旧状态值,导致第一次点击时这两个状态没有同步到最新数据,必须等第二次点击才能用上一次更新后的状态,因此出现两次点击才生效的问题。
方案一:提前计算新值,统一更新
直接在函数内计算出最新的索引和单词,基于这些确定的值更新所有状态,避免依赖未更新的state:
function resetGame(){ // 计算新索引,取余处理实现列表循环,防止越界 const newIndex = (numberInList + 1) % randomWordsList.length; const newWord = randomWordsList[newIndex]; setNumberInList(newIndex); setGeneratedWord(newWord); setGeneratedWordLetters( newWord.split("").map((letter) => { return { letter: letter.toUpperCase(), matched: false }; }) ); setFalseTries(0); }
方案二:用useEffect自动同步状态
将generatedWord和generatedWordLetters设置为依赖numberInList的衍生状态,通过useEffect监听索引变化自动更新,简化resetGame的逻辑:
function App() { const [numberInList, setNumberInList] = useState(0); const randomWordsList = ["comfort", "calm", "relax", "coffee", "cozy"]; const [generatedWord, setGeneratedWord] = useState( randomWordsList[numberInList] ); const [generatedWordLetters, setGeneratedWordLetters] = useState( randomWordsList[numberInList].split("").map((letter) => { return { letter: letter.toUpperCase(), matched: false }; }) ); const [falseTries, setFalseTries] = useState(0); // 监听numberInList变化,自动同步单词和字母状态 useEffect(() => { const currentWord = randomWordsList[numberInList]; setGeneratedWord(currentWord); setGeneratedWordLetters( currentWord.split("").map((letter) => ({ letter: letter.toUpperCase(), matched: false })) ); }, [numberInList, randomWordsList]); function resetGame(){ // 仅更新索引和错误次数,其余状态由useEffect自动处理 setNumberInList(prev => (prev + 1) % randomWordsList.length); setFalseTries(0); } // 其他组件逻辑... }
内容的提问来源于stack exchange,提问作者Michael Schulz
相关产品推荐
相关产品推荐

