React Vite项目组件渲染时setState警告的解决求助
解决React中“Cannot update a component while rendering a different component”警告
错误根源分析
- 违反React Hooks规则:在
data.map循环内部声明useState,Hooks必须在组件顶层调用,不能嵌套在循环、条件判断或子函数中。 - 渲染期间更新状态:在
AccordionItemState的渲染回调中直接调用setClassName,此时React正在渲染Context.Consumer(AccordionItemState内部的上下文消费者),却触发了Value组件的状态更新,导致渲染不一致警告。 - 缓存残留问题:删除代码后仍有警告,大概率是浏览器缓存或Vite热更新残留导致旧代码未完全替换。
解决方案
1. 移除无效状态管理,利用组件内置状态
直接使用react-accessible-accordion提供的expanded状态动态生成类名,无需额外维护className状态。
2. 修复Hooks使用方式
确保所有Hooks都在组件顶层调用,避免嵌套在循环或子函数中。
3. 清除缓存并重启服务
- 按
Ctrl+Shift+R强制刷新浏览器清除缓存 - 停止Vite开发服务器后重新启动(执行
npm run dev/yarn dev)
完整修正代码
import React from 'react'; import { Accordion, AccordionItem, AccordionItemHeading, AccordionItemButton, AccordionItemPanel, AccordionItemState } from 'react-accessible-accordion'; import { MdOutlineArrowDropDown } from 'react-icons/md'; import data from '../../utils/accordion'; import './value.css'; const Value = () => { return ( <section className="v-wrapper"> <div className="padding innerWidth flexCenter v-container"> {/* Left Side */} <div className="v-left"> <div className="image-container"> <img src="./value.png" alt="Value illustration" /> </div> </div> <div className="flexColStart v-right"> <span className="orangeText">Title</span> <span className="secondaryText">Why </span> <span className="secondaryText"> description</span> <Accordion className="accordion" allowMultipleExpanded={false} preExpanded={[0]} > {data.map((item, i) => ( <AccordionItem key={i} uuid={i} className={`accordionItem`} > <AccordionItemHeading> <AccordionItemButton className="flexCenter accordionButton"> <AccordionItemState> {({ expanded }) => ( <> <div className="flexCenter icon">{item.icon}</div> <span className="secondaryText">{item.heading}</span> <div className={`flexCenter icon ${expanded ? 'expanded' : 'collapsed'}`}> <MdOutlineArrowDropDown size={20} /> </div> </> )} </AccordionItemState> </AccordionItemButton> </AccordionItemHeading> <AccordionItemPanel> <p className="secondaryText">{item.detail}</p> </AccordionItemPanel> </AccordionItem> ))} </Accordion> </div> </div> </section> ); }; export default Value;
代码说明
- 移除了循环内的
useState声明,不再违反Hooks规则 - 直接通过
AccordionItemState提供的expanded状态动态控制类名,无需额外状态更新 - 避免了在渲染回调中触发状态更新的操作,彻底消除警告
内容的提问来源于stack exchange,提问作者Odai
相关产品推荐
相关产品推荐

