React点击按钮路由跳转时触发Cannot update a component错误求助
React状态更新与路由跳转冲突的解决方案
问题原因
你遇到的Warning: Cannot update a component (Home) while rendering a different component (Posts)警告,本质是触发路由跳转后,立刻更新了Home父组件App的状态——此时Home组件已经进入卸载流程,而Posts正在渲染,React禁止在一个组件渲染期间去更新另一个组件的状态,所以抛出警告。
解决方案
方案1:调整执行顺序(快速修复)
把状态更新放到路由跳转之前,确保Home组件还未开始卸载时完成状态更新:
<button key={e.id + 10} onClick={() => { // 先更新状态,再跳转路由 setResponse(e.id); navigate('/posts'); }} className="btn" > Posts </button>
方案2:用URL参数传递数据(更规范的做法)
依赖父组件状态传递页面数据不符合路由设计的初衷,改用URL参数传递userId,彻底避免状态同步冲突:
- 修改Home组件的跳转逻辑:
<button key={e.id + 10} onClick={() => { // 将userId放入URL参数 navigate(`/posts/${e.id}`); }} className="btn" > Posts </button>
- 更新App.js的路由配置:
function App() { // 不再需要这个共享状态 // const [response, setResponse] = useState({}); return ( <Router> <Routes> <Route exact path="/" element={<Home />} /> {/* 配置带参数的路由 */} <Route exact path="/posts/:userId" element={<Posts />} /> <Route exact path="*" /> </Routes> </Router> ); }
- 修改Posts组件获取参数:
import { useParams } from 'react-router-dom'; function Posts() { // 从URL参数中获取userId const { userId } = useParams(); const dispatch = useDispatch(); const navigate = useNavigate(); const state = useSelector((state) => state); if (state.post.isLoading) { return <h1>Loading...</h1>; } if (!state.post.data) { dispatch(fetchPosts()); } return ( <div className="App"> Posts {state.post.data && state.post.data {/* 注意转换参数类型(URL参数是字符串) */} .filter((e) => e.userId === parseInt(userId)) .map((e) => ( <div key={`${e.userId}-${e.id}`}> <li key={e.id}>{e.title}</li> </div> ))} <button onClick={() => navigate('/')}> List of users </button> </div> ); }
补充说明
你之前尝试在onClick里直接用useEffect的写法是错误的——React Hook只能在组件顶层或自定义Hook中调用,不能在事件回调这类嵌套函数里使用,所以这种写法根本不会生效。
内容的提问来源于stack exchange,提问作者vitalik
相关产品推荐
相关产品推荐

