reactjs - 在 mapStateToProps 中使用扩展运算符 (...) 会导致将过时的值传递给子组件
问题描述
我的组件有这样的代码,它是一个功能组件:
useEffect(() => {
if (errors['update'].error || successes['update'].success) {
setUpdateInProgress(false);
}
}, [errors['update'].error, successes['update'].success])
error
和success
属性相互独立,当其中任何一个为真时,我想调用setUpdateInProgress
.
在mapStateToProps
我有这样的代码:
const mapStateToProps = (store) => {
return {
// other fields
errors: {...store.prop1.errors, ...store.prop2.errors},
successes: {...store.prop1.errors, ...store.prop2.errors};
}
这些errors
和successes
对象是我需要发送到我的组件以useEffect
使其工作的道具。很明显,我想将多个地方的属性组合成一个(prop1
,,prop2
...)。
问题是,它不起作用,并且useEffect
没有调用。为了让它工作,我必须像下面这样拆分道具:
const mapStateToProps = (store) => {
return {
// other fields
prop1Errors: store.prop1.errors,
prop2Errors: store.prop2.errors,
prop1Successes: store.prop1.successes,
prop2Successes: store.prop2.successes
}
为什么扩展运算符会导致从状态设置陈旧值,而直接使用状态值不会?
编辑:对于那些感兴趣的人,errors
并且successes
有这样的结构:
errors: {
create: {
error: true,
message: "Error in create"
},
update: {
error: false,
message: ""
}
//... same thing for other actions like fetch, etc
}
//... same thing for successes
至于reducer代码,是这样的:
function reducer(state, action) {
if(action === "UPDATE") {
return {...state, errors: { ...state.errors, update: { message: '', error: false }}, successes: { ...state.successes, update: { message: 'Update successful.', success: true }}}
}
}
解决方案
对象初始化器中的扩展属性将它们自己的可枚举属性从提供的对象复制到新创建的对象上。如果新创建的对象中已经存在spread属性,则会自动替换。
换句话说,如果您有 2 个对象:const foo = {a: 1}
和const bar = {a: 2, b: 1}
. 的结果{...foo, ...bar}
将是{a: 2, b: 1}
。因此,您可以看到分配的a
属性是最后一个展开对象中的属性。
这正是你的情况。您必须考虑深度合并,因为您有一个用于错误和成功的多维结构。
根据您的错误结构,我将执行一个合并错误/成功的函数,如下所示:
const mergeMessages = (type, ...messages) =>
{
return messages.reduce((carry, message) => {
for (let [key, value] of Object.entries(message)) {
if (!carry.hasOwnProperty(key) || value[type] === true) {
carry[key] = value;
}
}
return carry;
}, {});
}
然后你可以像这样使用它:
const mapStateToProps = (store) => {
return {
// other fields
errors: mergeMessages('error', store.prop1.errors, store.prop2.errors),
successes: mergeMessages('success', store.prop1.successes, store.prop2.successes),
}
}
推荐阅读
- ruby - 如何测试函数的逻辑但忽略方法调用?
- python-3.x - 根据条件重复行和交换 clumns
- java - Keycloak:身份代理时不要创建本地用户
- c++ - 在一个线程中为多个消费者异步读取一个套接字
- ansible - 如何使用通配符包含多个文件以在 Ansible 中使用环境变量?
- python - 在 Visual Studio 中以交互方式运行时 Python 脚本找不到文件
- python - 从图像中识别文本(数字和字符)
- c# - 多线程的多次迭代
- anylogic - Anylogic 中 Wall 的 contains() 函数中的错误
- bash - 使用 bash 和 wget 下载具有不同扩展名的文件