React开发10x10动物网格时Node组件内容被意外修改问题求解
问题原因
- 动物随机逻辑位置错误:你把动物类型生成的
handleAnimalState方法放在了Node组件的render函数里调用,每次Grid组件state变化触发重渲染时,所有已激活的Node都会重新随机生成动物类型,直接导致旧动物被新类型替换。 - 定时器重复创建无清理:每次点击按钮都会创建一个新的
setInterval定时器,多次点击后会同时运行多个定时器,动物生成速度会越来越快,也会引发状态更新混乱。 - state直接修改不符合React规范:你直接调用
this.state.currentFields.push(newAnimalId)修改原state数组,属于违反React不可变更新原则的操作,可能引发渲染异常。
修复方案
1. 改造state结构,存储每个位置对应的动物类型
把Grid组件的state从只存位置ID,改成存{id: 位置ID, type: 动物类型}的对象数组,动物类型在生成新动物的时候就确定,而不是渲染的时候随机:
// Grid组件定时器逻辑改造 setInterval(() => { const newAnimalId = getRandomId(this.state.currentFields.map(item => item.id)); this.handleRemovalOfFieldFromGrid(newAnimalId); // 预先生成动物类型 const animalTypes = []; for (let i = 1; i <= 100; i++) { animalTypes.push("sheep"); if (i % 20 === 0) animalTypes.push("bear"); if (i % 10 === 0) animalTypes.push("wolf"); } const randomIdx = Math.floor(Math.random() * animalTypes.length); const newAnimal = { id: newAnimalId, type: animalTypes[randomIdx] } // 不可变方式更新数组,不修改原state this.setState({ currentFields: [...this.state.currentFields, newAnimal], }); }, 1000);
2. 给定时器加标识,避免重复创建
在Grid组件的constructor里添加定时器实例存储,点击时先判断是否已有定时器,有就不重复创建,组件卸载时清理定时器:
// constructor里新增存储变量 this.timer = null; // handleClick里的定时器创建逻辑修改 if (!this.timer) { this.timer = setInterval(() => { // 原有定时器逻辑 }, 1000) } // 新增组件卸载生命周期清理定时器 componentWillUnmount() { clearInterval(this.timer) }
3. 改造Node组件,直接从props拿动物类型
删除Node组件里的随机生成逻辑,直接根据传入的currentFields匹配对应位置的动物类型:
// Node组件render逻辑修改 render() { const currentAnimal = this.props.currentFields.find(item => item.id === this.props.id); const animalIfIdInGridAndIsNotMarked = currentAnimal && !this.props.fieldsNotMarked.includes(this.props.id) ? currentAnimal.type : ""; return <div className="node">{animalIfIdInGridAndIsNotMarked}</div>; }
内容的提问来源于stack exchange,提问作者brovia
相关产品推荐
相关产品推荐

