如何阻止部分React组件在其他组件状态变更时重渲染
问题解决:React中保持圆形初始位置不随重渲染改变
问题描述
需要渲染若干个随机定位的圆形,每个圆形带数值参数,点击后数值累加到左上角总分,同时圆形消失。当前功能正常,但点击时其他圆形会重新渲染并生成新随机位置,需让每个圆形初始位置仅生成一次。
问题根源
每次调用setCount更新总分时,组件会触发重新渲染,renderCircles函数会被再次执行,重新生成所有圆形的随机位置;同时ctr是普通变量,每次渲染都会重置,导致DOM id重复;直接操作DOM修改可见性的方式也不符合React状态驱动的设计理念。
解决方案
用React状态存储所有圆形的初始数据(包括位置、颜色、数值和显示状态),渲染时直接基于状态生成圆形,点击时通过更新状态来修改总分和对应圆形的显示状态:
修改后的完整代码
import { useState, useEffect } from "react"; import "./App.css"; function App() { const [count, setCount] = useState(0); const [circles, setCircles] = useState([]); // 生成随机数工具函数 function getRandom(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min) + min); } // 初始化圆形数据,仅在组件挂载时执行一次 useEffect(() => { const colorKeys = Object.keys(Color); const initialCircles = Array.from({ length: 15 }, () => ({ id: Math.random().toString(36).slice(2), xPos: getRandom(3, 53), yPos: getRandom(3, 40), color: colorKeys[Math.floor(Math.random() * colorKeys.length)], value: getRandom(1, 100), isVisible: true })); setCircles(initialCircles); }, []); // 处理圆形点击事件 const handleCircleClick = (circle) => { setCount(prev => prev + circle.value); setCircles(prev => prev.map(c => c.id === circle.id ? {...c, isVisible: false} : c )); }; return ( <div className="App"> <div className="App-game"> {circles.filter(c => c.isVisible).map(circle => ( <div key={circle.id}> <svg className="circle" onClick={() => handleCircleClick(circle)} style={{ left: `calc(${circle.xPos}vw - 60px)`, top: `calc(${circle.yPos}vw - 60px)`, position: "absolute", visibility: circle.isVisible ? "visible" : "hidden" }} > <circle cx={30} cy={30} r={30} fill={circle.color} /> </svg> </div> ))} </div> <div className='App-currency' style={{color: "black", fontSize: 80}}> {count} </div> </div> ); } export default App; class Color { static Green = new Color("green"); static Blue = new Color("blue"); static Yellow = new Color("yellow"); static Red = new Color("red"); static Pink = new Color("pink"); static Orange = new Color("orange"); constructor(name) { this.name = name; } toString() { return `Color.${this.name}`; } }
关键改动说明
- 使用
useState存储circles数组,每个元素包含圆形的唯一id、位置、颜色、数值和显示状态 - 用
useEffect配合空依赖数组,仅在组件挂载时生成一次圆形初始数据,确保位置不会随重渲染改变 - 点击事件不再直接操作DOM,而是通过更新
circles状态中对应圆形的isVisible属性来控制显示/隐藏 - 用每个圆形的唯一
id作为React元素的key,避免渲染时的性能问题和标识错误 - 更新总分时使用函数式更新(
setCount(prev => prev + circle.value)),确保获取到最新的状态值
内容的提问来源于stack exchange,提问作者Ernest P W
相关产品推荐
相关产品推荐

