React中如何执行完useState赋值逻辑后再触发Link路由跳转
问题根因
你遇到的问题本质是两个原因叠加导致的:
- React的
useState赋值是异步批量更新的,调用setResData、setLinkName后不会立刻更新当前渲染周期里的rstData、linkName变量,要等到组件重渲染后才会拿到新值 - 包裹点击区域的
Link组件的跳转行为是同步触发的,点击时会直接用当前渲染周期里的旧参数跳转,根本等不到state更新和组件重渲染
最优解决方案(推荐)
完全不需要用state存储要传递的参数,直接在点击事件里拿到当前餐厅的信息后,手动控制路由跳转即可,从根源上规避异步state的问题。
第一步:修改Restaurant_Item组件
这里以react-router-dom v5为例,v6仅需替换为useNavigateAPI即可:
import React from 'react'; import {useHistory} from 'react-router-dom'; // 替换原来的Link导入 function Restaurant_Item({rlist}) { const history = useHistory(); let rlist_tmp = []; const goDetail = (rkey) => { // 直接拿到当前餐厅数据,不需要存state const currentRst = rlist[rkey]; // 手动跳转,参数直接传入 history.push({ pathname :"/restaurant_result", search : `?sort=${currentRst.restName}`, state: {data : currentRst} }) } for (let rkey in rlist) { rlist_tmp.push( // 去掉Link包裹,直接绑定点击事件 <div className="rst_list_cell" onClick={() => goDetail(rkey)} key={rkey}> <div> <button className="rst_list_name"> {rlist[rkey].restName} </button> <div className="rst_list_position"> {rlist[rkey].address} </div> </div> </div> ) } return (<div> {rlist_tmp} </div>); } export default Restaurant_Item;
第二步:修改详情页取值逻辑
路由state参数不是通过组件props传递的,需要通过useLocation获取:
import React from 'react'; import {Link, useLocation} from "react-router-dom"; import Restaurant_result_axios from './Restaurant_result_axios.js'; import backicon from "../assets/backicon.png"; const Restaurant_result = () => { // 从路由location中拿到传递的参数 const location = useLocation(); const data = location.state?.data; console.log(data) return ( <div> <Link to="./restaurant_list"><img className="backicon" src={backicon} alt="backicon"/> </Link> <div className="rst_result_prom"/> <div className="rst_result_cell"> <div> <div className="rst_result_name"> {data?.restName} </div> <div className="rst_result_position"> {data?.address} </div> </div> </div> </div> ); }; export default Restaurant_result;
兼容方案(保留原Link写法,不推荐)
如果一定要保留原Link的写法,可以通过阻止默认跳转+监听state更新的方式实现,冗余度较高:
- 给点击事件加
e.preventDefault()阻止Link默认跳转行为 - 新增
useEffect监听rstData和linkName的变化,两个值更新后再手动调用路由跳转API触发跳转
内容的提问来源于stack exchange,提问作者C12H22O12
相关产品推荐
相关产品推荐

