ReactJS Redux变量updateLog未正确更新问题求助
问题描述
已通过Redux DevTools确认dispatch执行正常,updateLog的值也已正确写入store,但调用FetchUpdateList()时,它读取的始终是updateLog的旧状态值。
相关代码
存储变量定义
var updateLog = useSelector((state) => state.updateLog.value);
触发复选框
<Checkbox checked={checkBoxActive} onChange={HandleCheckBox} />
复选框处理函数
function HandleCheckBox(event) { dispatch(setUpdateLog({ 'start': 0, 'end': 10, 'viewOneUser': !updateLog.viewOneUser })) console.log("...Running HandleCheckBox()...") console.log(event.target.checked); setLoadingMore(true); setCheckBoxActive(event.target.checked); ResetValues(); setTimeout(() => FetchUpdateList(), 2000); } function ResetValues() { console.log("...Running ResetValues()...") setUpdateList([]); setMoreEnabled(true); }
读取旧值的FetchUpdateList()
async function FetchUpdateList() { setLoadingMore(true); console.log(updateLog); if (updateLog.viewOneUser) { var call = await GetUpdateListAPI(props.instance, props.accounts, updateLog.start, updateLog.end, null, profileData.user == "" ? localStorage.getItem('user') : profileData.user); } else { var call = await GetUpdateListAPI(props.instance, props.accounts, updateLog.start, updateLog.end, null, null); } if (call.Success) { var list = []; setUpdatesLength(call.Length); dispatch(setUpdateLog({ 'start': updateLog.start + 10, 'end': updateLog.end + 10, 'viewOneUser': updateLog.viewOneUser })) // 剩余代码省略 } }
Redux Store配置
const updateLogSlice = createSlice({ name: 'updateLog', initialState: { value: {'start': 0, 'end': 10, 'viewOneUser': false}, }, reducers: { setUpdateLog: (state, action) => { state.value = action.payload }, }, }) export const { setUpdateLog } = updateLogSlice.actions export default configureStore({ reducer: { // 其他reducer省略 updateLog: updateLogSlice.reducer, }, })
核心原因
这是React闭包特性导致的问题:HandleCheckBox执行时,setTimeout捕获的是当前渲染周期的updateLog值(也就是dispatch前的旧值),2秒后调用FetchUpdateList时,依然使用这个旧闭包里的变量,而非store更新后的新值。
解决方案
方法一:直接传递最新参数到FetchUpdateList
在HandleCheckBox中提前计算出新值,直接传给FetchUpdateList,彻底避开闭包依赖:
function HandleCheckBox(event) { const newViewOneUser = !updateLog.viewOneUser; dispatch(setUpdateLog({ 'start': 0, 'end': 10, 'viewOneUser': newViewOneUser })) // ...其他代码 setTimeout(() => FetchUpdateList(newViewOneUser), 2000); } async function FetchUpdateList(viewOneUser) { setLoadingMore(true); if (viewOneUser) { var call = await GetUpdateListAPI(props.instance, props.accounts, 0, 10, null, profileData.user == "" ? localStorage.getItem('user') : profileData.user); } else { var call = await GetUpdateListAPI(props.instance, props.accounts, 0, 10, null, null); } if (call.Success) { setUpdatesLength(call.Length); dispatch(setUpdateLog({ 'start': 10, 'end': 20, 'viewOneUser': viewOneUser })) } }
方法二:直接从store获取最新状态
在FetchUpdateList内部通过store实例获取最新值,不依赖闭包中的变量:
import { useStore } from 'react-redux'; // 组件内获取store实例 const store = useStore(); async function FetchUpdateList() { setLoadingMore(true); // 直接取store里的最新值 const latestUpdateLog = store.getState().updateLog.value; console.log(latestUpdateLog); if (latestUpdateLog.viewOneUser) { var call = await GetUpdateListAPI(props.instance, props.accounts, latestUpdateLog.start, latestUpdateLog.end, null, profileData.user == "" ? localStorage.getItem('user') : profileData.user); } else { var call = await GetUpdateListAPI(props.instance, props.accounts, latestUpdateLog.start, latestUpdateLog.end, null, null); } if (call.Success) { setUpdatesLength(call.Length); dispatch(setUpdateLog({ 'start': latestUpdateLog.start + 10, 'end': latestUpdateLog.end + 10, 'viewOneUser': latestUpdateLog.viewOneUser })) } }
内容的提问来源于stack exchange,提问作者Kyle Andrew
相关产品推荐
相关产品推荐

