React中useMemo内调用setState触发非法组件状态更新错误如何解决?
报错原因
useMemo 属于 React 渲染阶段执行的钩子,回调逻辑会在组件渲染过程中同步运行。你的代码在useMemo回调内直接调用父组件传入的setSearchResult修改父组件状态,相当于在SearchCharacters组件还没完成渲染的时候,就触发了父组件Characters的重渲染,违反了React要求渲染过程必须为无副作用纯函数的规则,因此触发非法状态更新警告。
此外,useMemo的设计定位是缓存计算量较大的返回值,本身不应该用来执行修改状态这类副作用操作,属于API误用。
修复方案
方案1:用useEffect替代useMemo执行副作用(改动最小)
useEffect会在组件渲染完成后才执行回调,不会在渲染过程中干扰其他组件状态,同时补全依赖数组的所有依赖项即可:
import React, { useEffect, useState } from "react"; import "./SearchCharacters.css"; function SearchCharacters({ charactersInfo, setSearchResult }) { const [searchText, setSearchText] = useState(""); // 替换useMemo为useEffect useEffect(() => { const findCharacter = charactersInfo.filter((character) => { return ( character.gender.toLowerCase() === searchText.toLowerCase() || character.species.toLowerCase() === searchText.toLowerCase() || character.status.toLowerCase() === searchText.toLowerCase() ); }); setSearchResult(findCharacter.length > 0 ? findCharacter : null); // 补全所有依赖项 }, [searchText, charactersInfo, setSearchResult]); return ( <div className="search_container"> <input className="search_input" onChange={(e) => setSearchText(e.target.value)} placeholder="Enter characters full name" /> </div> ); } export default SearchCharacters;
方案2:状态上移符合单向数据流(更推荐)
将搜索逻辑完全放到父组件实现,子组件仅负责输入控制和传递搜索关键字,不需要直接操作父组件状态:
- 子组件不再接收
setSearchResult,只在searchText变化时通过回调传给父组件 - 父组件接收
searchText后自行用useMemo计算搜索结果,避免跨组件状态修改
方案3:直接返回搜索结果
如果组件结构允许,你可以直接将搜索结果作为useMemo的返回值对外暴露,不需要通过setState跨组件传递,完全规避副作用:
// 子组件内部逻辑 const searchResult = useMemo(() => { const findCharacter = charactersInfo.filter((character) => { return ( character.gender.toLowerCase() === searchText.toLowerCase() || character.species.toLowerCase() === searchText.toLowerCase() || character.status.toLowerCase() === searchText.toLowerCase() ); }); return findCharacter.length > 0 ? findCharacter : null; }, [searchText, charactersInfo]); // 父组件可直接读取该返回值使用
内容的提问来源于stack exchange,提问作者user14587589
相关产品推荐
相关产品推荐

