吊死鬼游戏开发:用useRef和useEffect对比新旧数组长度
解决吊死鬼游戏中对比新旧猜字母数组的问题
我懂你要实现的逻辑——当用户输入字母后,判断这次输入是不是新增的、未重复的有效字母,本质是对比去重后的旧数组和新数组是否有差异对吧?直接用oldArray !== newUpdatedArray肯定行不通,因为数组是引用类型,哪怕内容完全一样,不同的数组引用也会返回true,更别说内容不同的情况了。你想到用useRef来处理是完全正确的思路,它能帮我们跨渲染周期保存上一次的数组状态,完美用来做新旧对比。
下面给你具体的实现方案:
1. 用useRef存储去重后的旧数组
首先在组件里声明一个ref,用来保存上一次去重后的猜字母数组:
import { useState, useEffect, useRef } from 'react'; // 你的其他组件逻辑... const guessedUniqueRef = useRef([]); // 初始化空数组,用来存去重后的旧数组
2. 修改counter函数实现对比逻辑
接下来调整你的counter函数,我们先对当前输入的数组去重,再和ref里的旧数组对比(可以先对比长度,简单高效;如果要更严谨也可以对比数组内容):
const counter = (letterArray) => { // 对当前输入的数组去重,得到唯一字母数组 const currentUniqueArray = letterArray.filter((v, i) => letterArray.indexOf(v) === i); // 对比新旧数组:长度不同说明有新字母加入 const isNewLetterAdded = currentUniqueArray.length !== guessedUniqueRef.current.length; if (isNewLetterAdded) { console.log('用户输入了新的有效字母!'); // 这里可以写你需要的逻辑,比如更新游戏状态、不扣错误次数等 } else { console.log('用户输入了重复字母!'); // 比如提示用户重复,或者不增加猜数次数 } // 更新ref,把当前去重后的数组存起来,供下一次对比使用 guessedUniqueRef.current = currentUniqueArray; };
3. 优化useEffect的依赖问题
另外,你的useEffect依赖里同时加了guessed和count,每次这两个值变化都会重新绑定事件,其实可以用函数式更新来优化,减少不必要的依赖:
useEffect(() => { const checkLetter = (event) => { // 只处理A-Z的字母键 if (event.keyCode < 65 || event.keyCode > 90) return; const letter = String.fromCharCode(event.keyCode).toLowerCase(); // 这里也可以提前判断字母是否重复,避免不必要的状态更新 if (!guessed.includes(letter)) { // 用函数式更新setCount,不用把count加入依赖 setCount(prevCount => prevCount + 1); setGuessed(prev => { const nextGuessed = [...prev, letter]; counter(nextGuessed); return nextGuessed; }); } else { console.log('这个字母已经猜过啦!'); } }; document.addEventListener('keydown', checkLetter); return () => document.removeEventListener('keydown', checkLetter); }, [guessed]); // 现在依赖只有guessed,避免不必要的重新绑定
这里为什么用useRef?因为useRef的特性是它的.current属性值变化不会触发组件重渲染,而且能在组件的整个生命周期里保存状态,正好适合存储上一次的数组状态,用来和当前的数组做对比,完全符合你的需求。
内容的提问来源于stack exchange,提问作者frontend
相关产品推荐
相关产品推荐

