Redux状态更新后函数内无法获取最新值问题求助
问题:Redux状态更新后函数内获取旧值的解决方案
问题描述
我尝试将Redux状态receiver的值发送至后端,但遇到一个问题:用于发送状态的函数内部,receiver的值与外部的不一致。
注意:这不是不可变性/组件未重新渲染的问题
代码片段:
const { logged, receiver } = useSelector( (state: RootState) => state.loggedAndReceiver ); console.log("Receiver1: ", receiver); async function getMessage(e: React.MouseEvent<HTMLElement, MouseEvent>) { e.preventDefault(); const target = e.target as HTMLElement; await dispatch(setReceiver(target.innerText)); console.log("Receiver: ", receiver); try { const url = "http://localhost:3001/loadChat?logged=" + logged + "&reciever=" + receiver; const response = await fetch(url); const jsonData = await response.json(); dispatch(setMessage(jsonData)); } catch (error: any) { console.log(error.message); } }
外部的console.log("Receiver1: ", receiver);能正确打印receiver的最新值,但函数内部的console.log("Receiver: ", receiver);打印的却是之前的旧状态。如何在函数内获取并使用最新的Redux状态发送至服务器?
原因分析
函数getMessage是在组件当前渲染周期内创建的,它捕获的是当前渲染时的receiver值。即便调用dispatch(setReceiver(...))更新了Redux状态,这个函数里的receiver依然是创建时的旧值——因为Redux状态更新会触发组件重新渲染,生成新的getMessage函数,但当前正在执行的还是旧的那个。
另外,dispatch本身是同步的,但状态更新不会立即改变当前渲染周期里的receiver变量,要等到下一次渲染才会更新。
解决办法
1. 直接使用触发更新的原始值
既然你是用target.innerText来更新receiver的,那直接把这个值拿来用就好,不用从Redux状态里取:
async function getMessage(e: React.MouseEvent<HTMLElement, MouseEvent>) { e.preventDefault(); const target = e.target as HTMLElement; const newReceiver = target.innerText; await dispatch(setReceiver(newReceiver)); console.log("Receiver: ", newReceiver); try { const url = "http://localhost:3001/loadChat?logged=" + logged + "&reciever=" + newReceiver; const response = await fetch(url); const jsonData = await response.json(); dispatch(setMessage(jsonData)); } catch (error: any) { console.log(error.message); } }
2. 直接从Redux Store获取最新状态
如果必须从Redux状态里取最新值,可以直接调用store.getState()(前提你能拿到store实例):
// 先导入你的Redux Store实例 import store from './path/to/your/store'; async function getMessage(e: React.MouseEvent<HTMLElement, MouseEvent>) { e.preventDefault(); const target = e.target as HTMLElement; await dispatch(setReceiver(target.innerText)); // 直接从Store获取最新的receiver值 const latestReceiver = store.getState().loggedAndReceiver.receiver; console.log("Receiver: ", latestReceiver); try { const url = "http://localhost:3001/loadChat?logged=" + logged + "&reciever=" + latestReceiver; const response = await fetch(url); const jsonData = await response.json(); dispatch(setMessage(jsonData)); } catch (error: any) { console.log(error.message); } }
3. 用useEffect监听状态变化触发请求
如果你的场景是状态更新后需要自动触发请求,可以把请求逻辑放到useEffect里,监听receiver的变化:
const { logged, receiver } = useSelector( (state: RootState) => state.loggedAndReceiver ); // 监听receiver变化,自动触发请求 useEffect(() => { async function fetchChat() { if (!receiver) return; try { const url = "http://localhost:3001/loadChat?logged=" + logged + "&reciever=" + receiver; const response = await fetch(url); const jsonData = await response.json(); dispatch(setMessage(jsonData)); } catch (error: any) { console.log(error.message); } } fetchChat(); }, [receiver, logged, dispatch]); async function getMessage(e: React.MouseEvent<HTMLElement, MouseEvent>) { e.preventDefault(); const target = e.target as HTMLElement; await dispatch(setReceiver(target.innerText)); }
内容的提问来源于stack exchange,提问作者Muathcs
相关产品推荐
相关产品推荐

