React警告:渲染NodeGroup时更新ShowScore组件状态异常解决方案
解决React渲染期间更新状态的警告问题
问题原因
控制台抛出的Cannot update a component ('ShowScore') while rendering a different component ('NodeGroup')警告,是因为你在AnimatedProgressProvider的渲染回调函数中调用了setPerValue——React要求组件的渲染函数必须是纯函数,不能包含状态更新这类副作用,否则会打乱组件的渲染流程,导致状态与视图不一致。
最优解决方案
方案1:手动实现动画逻辑,替代AnimatedProgressProvider
直接用requestAnimationFrame在副作用中驱动动画,避免在渲染阶段更新状态:
- 保留
perValue状态,删除AnimatedProgressProvider相关代码,在组件内部添加以下useEffect实现动画:
useEffect(() => { let animationId; const startTime = performance.now(); const duration = 200; // 对应原动画的0.2秒时长 const animate = (currentTime) => { const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); const easedProgress = easeQuadInOut(progress); const currentValue = percentage * easedProgress; const rounded = Math.round(currentValue); setPerValue(rounded); if (progress < 1) { animationId = requestAnimationFrame(animate); } }; animationId = requestAnimationFrame(animate); // 组件卸载时取消动画 return () => cancelAnimationFrame(animationId); }, [percentage]);
- 修改进度条组件的
value属性,直接使用perValue:
<CircularProgressbarWithChildren value={perValue} strokeWidth={5} styles={buildStyles({ pathTransition: "none", textColor: "#ef5488", trailColor: '#f5f5f8', pathColor: percentage >= Number(systemconfig.maximum_coins_winning_percentage) ? "#15ad5a" : "#ef5488", })} > <img src={userData.data && userData.data.profile ? userData.data.profile : process.env.PUBLIC_URL + "/images/user.webp"} alt="user" className="showscore-userprofile" onError={imgError}/> </CircularProgressbarWithChildren>
方案2:移除perValue状态,直接使用动画回调值
如果不想手动实现动画,可以调整布局,将百分比展示元素放到AnimatedProgressProvider的回调内部,直接使用动画过程中的值,无需状态存储:
删除
const [perValue, setPerValue] = useState(0);这一行修改进度条所在的列,将百分比展示移到动画回调中:
<div className="col-md-2 col-4 coin_score_screen score-section text-center bold"> <div className="d-inline-block"> <AnimatedProgressProvider valueStart={0} valueEnd={percentage} duration={0.2} easingFunction={easeQuadInOut}> {(value) => { const roundedValue = Math.round(value); return ( <> <CircularProgressbarWithChildren value={value} strokeWidth={5} styles={buildStyles({ pathTransition: "none", textColor: "#ef5488", trailColor: '#f5f5f8', pathColor: percentage >= Number(systemconfig.maximum_coins_winning_percentage) ? "#15ad5a" : "#ef5488", })} > <img src={userData.data && userData.data.profile ? userData.data.profile : process.env.PUBLIC_URL + "/images/user.webp"} alt="user" className="showscore-userprofile" onError={imgError}/> </CircularProgressbarWithChildren> {/* 原布局中的百分比展示移到这里 */} <div className="col-4 col-md-2 right_wrong_screen text-center percent_value"> <h1 className="winlos percentage">{roundedValue}%</h1> </div> </> ); }} </AnimatedProgressProvider> </div> </div>
- 删除原布局中单独的百分比展示div:
<!-- 删除这部分 --> <div className="col-4 col-md-2 right_wrong_screen text-center percent_value"> <h1 className="winlos percentage">{perValue}%</h1> </div>
两种方案都能解决警告问题,方案1无需调整布局,逻辑更独立;方案2更简洁,适合不想改动动画逻辑的场景。
内容的提问来源于stack exchange,提问作者Mayani Sumit
相关产品推荐
相关产品推荐

