React/Redux异步问题:dispatch更新store后调用接口参数为undefined如何解决
解决方案
这个问题的核心是组件闭包捕获的client_id是当前渲染周期的旧值:dispatch更新Redux状态后,需要触发组件重渲染,下一次渲染时useSelector才会返回最新的client_id,但你在dispatch之后立刻调用的getFleetFilter还是当前渲染闭包里的旧值。
你可以根据业务场景选择以下三种方案:
方案1:直接传参调用(最简单,推荐)
你在clientChange函数中已经拿到了最新的client_id,直接作为参数传给getFleetFilter即可,不需要依赖Redux更新后的状态:
修改Form.js中的调用逻辑:
const clientChange = (event) => { const client = event.target.value; const client_id = client.id; dispatch({ type: "CLIENT_LIST_SELECTION", payload: client_id }); // 直接传入最新的client_id getFleetFilter(client_id); };
修改Search.js中的getFleetFilter接收参数:
const getFleetFilter = async (clientId) => { dispatch({ type: "FLEET_LIST_REQUEST" }); try { // 优先使用传入的最新clientId let res = await getFleet(token, clientId); let data = res.data.data dispatch({ type: "FLEET_LIST_LOAD", payload: data }); } catch (err) { console.log("Error Fleet Data", err); }; };
方案2:用useEffect监听状态变化
如果有多个场景会修改client_id,可以通过监听client_id的变化自动触发请求,不需要手动调用:
在Search.js中新增useEffect逻辑,同时删掉Form.js里的getFleetFilter()调用:
// Search.js中新增 useEffect(() => { // 只有client_id存在时才发起请求 if (client_id) { getFleetFilter(); } }, [client_id])
方案3:将请求逻辑封装为Redux Thunk
如果你的项目已经开启了Redux Thunk中间件(Redux Toolkit默认开启),可以把请求逻辑放到thunk中,直接从store获取最新状态,完全避开组件闭包问题:
首先定义thunk:
// 放在Redux相关的逻辑文件中 export const fetchFleetList = () => async (dispatch, getState) => { dispatch({ type: "FLEET_LIST_REQUEST" }); try { // 直接从最新的store中获取client_id const client_id = getState().client.selection; const token = getState().auth.token; // 把token也放到store里的话可以统一管理 let res = await getFleet(token, client_id); let data = res.data.data dispatch({ type: "FLEET_LIST_LOAD", payload: data }); } catch (err) { console.log("Error Fleet Data", err); }; }
然后修改Form.js的调用逻辑:
import { fetchFleetList } from '你的redux文件路径' const clientChange = (event) => { const client = event.target.value; const client_id = client.id; dispatch({ type: "CLIENT_LIST_SELECTION", payload: client_id }); // 直接dispatch thunk即可,不需要传参 dispatch(fetchFleetList()); };
内容的提问来源于stack exchange,提问作者Yuriy Horbatenko
相关产品推荐
相关产品推荐

