React状态多次升降传递后组件过滤出现更新警告问题排查
问题还原
组件结构
"Main" |--"Side"--"CategoryPicker" | |--"ItemBoard"
实现步骤代码
CategoryPicker获取选中值:
const filterResultHandler = (e) => { props.onFilterChange(e.target.value); } ... onChange={filterResultHandler}
- 将值提升至
Side组件:
const [filterState, setFilterState] = useState("all"); const onFilterChangeHandler = () => { props.onPassData(setFilterState);}; ... <CategoryPicker selected={filterState} onFilterChange={onFilterChangeHandler} />
- 将值再次提升至
Main组件(至此console.log值显示正常):
const [recData, setRecData] = useState("all"); const onFilterChangeHandler = (passedData) => { setRecData(passedData); }; <Side onPassData={onFilterChangeHandler} selected={recData} />
- 将值作为props传递给
ItemBoard:
<ItemBoard items={items} recData={recData} />
- 在
ItemBoard中过滤数组并渲染:
const filteredProducts = props.items.filter((product) => { return (product.cat.toString() === props.recData) }) {filteredProducts.map((product, index) => ( <Item cat={product.cat} /> ))}
出现的警告
Warning: Cannot update a component (
Side) while rendering a different component (Main). To locate the bad setState() call insideMain
提问
请问我的逻辑哪里出错了?注:目前只想理解状态提升与props传递的原理,暂不寻求其他替代方案。
问题分析与修正
问题核心是你在Side组件里把自身的状态更新函数setFilterState直接传给了Main组件,导致Main调用这个函数时,相当于在自身渲染流程中触发了Side的状态更新,违反了React的规则:不能在组件渲染过程中更新另一个组件的状态。
具体错误点在Side的onFilterChangeHandler:
// 错误:传递的是状态更新函数而非选中值 const onFilterChangeHandler = () => { props.onPassData(setFilterState);};
正确的状态提升流程应该是:
CategoryPicker把选中值传给SideSide先更新自己的filterState,再把具体的选中值传给MainMain用收到的值更新自身的recData,再传给ItemBoard
修正后的Side组件代码:
const [filterState, setFilterState] = useState("all"); // 接收选中值,先更新自身状态,再传递值给Main const onFilterChangeHandler = (selectedValue) => { setFilterState(selectedValue); props.onPassData(selectedValue); }; ... <CategoryPicker selected={filterState} onFilterChange={onFilterChangeHandler} />
这样整个数据流转是:CategoryPicker选中值 → Side更新状态并传值给Main → Main更新recData → 传给ItemBoard筛选,所有状态更新都在事件回调中触发,不会出现跨组件渲染时更新状态的问题。
内容的提问来源于stack exchange,提问作者Jakub
相关产品推荐
相关产品推荐

