React Toolkit Query Dispatch异常:循环中encryptedKeys状态被覆盖
问题原因及解决方案
核心问题
- 闭包捕获旧状态:循环中调用的
getKeys函数都捕获了同一个初始的encryptedKeys状态值(比如空数组),当异步请求完成后,所有dispatch(setEncryptedKeys([...encryptedKeys, data]))都是基于这个旧值更新,最终只会保留最后一次请求返回的密钥。 - 参数传递错误:
getKeys函数里调用createEncryptionKey(data)时,data未定义,无法正确向API传递参数。
修复步骤
1. 使用函数式更新状态
Redux的setEncryptedKeys支持函数式更新,传入的函数会接收当前最新的状态,这样就能避免闭包带来的旧状态问题。
2. 修正参数传递
给getKeys函数添加参数,传递每个文件对应的API请求数据,确保请求能正确发送。
3. 处理异步调用(可选)
如果需要保证密钥生成完成后再更新文件列表,可以用Promise.all等待所有请求完成。
修改后的代码
DragDrop组件
function DragDrop() { const dispatch = useDispatch(); const files = useSelector((state) => state.file.uplaodedFiles); const [createEncryptionKey] = useCreateEncryptionKeyMutation(); // 修改getKeys,接收API请求所需的参数 const getKeys = async (apiData) => { try { const data = await createEncryptionKey(apiData).unwrap(); if (data) { // 使用函数式更新,基于最新状态添加新密钥 dispatch(setEncryptedKeys(prevKeys => [...prevKeys, data])); } } catch (err) { console.log(err); } }; const handleChange = async (file) => { let arr = []; // 收集所有异步请求 const keyPromises = []; for (let i = 0; i < file.length; i++) { const fileItem = file[i]; // 假设需要根据file生成API所需的key参数,这里根据实际逻辑调整 const apiData = { key: /* 生成key的逻辑,比如基于fileItem的信息 */ }; keyPromises.push(getKeys(apiData)); const data = { file: fileItem, }; arr.push(data); } // 可选:等待所有密钥生成完成后再更新文件列表 await Promise.all(keyPromises); dispatch(setUplaodedFiles([...files, ...arr])); }; }
补充说明
- 函数式更新
prevKeys => [...prevKeys, data]确保每次更新都基于Redux store中的最新状态,不会因为闭包捕获旧值导致覆盖。 - 调整
getKeys的参数传递,确保API请求能拿到正确的key参数,根据你的业务逻辑补充apiData的生成规则。 - 使用
Promise.all等待所有密钥请求完成,保证文件列表更新时,对应的密钥已经存入状态(如果业务不需要强顺序,也可以去掉这一步)。
内容的提问来源于stack exchange,提问作者Viktor Silvestrov
相关产品推荐
相关产品推荐

