Reactjs 在MapStateTops中使用扩展运算符(…)会导致将过时值传递给子组件
我的组件是一个功能组件,其代码如下:Reactjs 在MapStateTops中使用扩展运算符(…)会导致将过时值传递给子组件,reactjs,react-redux,Reactjs,React Redux,我的组件是一个功能组件,其代码如下: useEffect(() => { if (errors['update'].error || successes['update'].success) { setUpdateInProgress(false); } }, [errors['update'].error, successes['update'].success]) error和success属性彼此独立,如果其中一个属性为true,我想调用setUpdateInPro
useEffect(() => {
if (errors['update'].error || successes['update'].success) {
setUpdateInProgress(false);
}
}, [errors['update'].error, successes['update'].success])
error
和success
属性彼此独立,如果其中一个属性为true,我想调用setUpdateInProgress
在MapStateTrops
中,我有如下代码:
const mapStateToProps = (store) => {
return {
// other fields
errors: {...store.prop1.errors, ...store.prop2.errors},
successes: {...store.prop1.errors, ...store.prop2.errors};
}
errors: {
create: {
error: true,
message: "Error in create"
},
update: {
error: false,
message: ""
}
//... same thing for other actions like fetch, etc
}
//... same thing for successes
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 }}}
}
}
这些错误
和成功
对象是我需要发送到组件的道具,以便useffect
工作。很明显,我希望将多个位置的属性合并到一个位置(prop1
,prop2
,…)
问题是,它不工作,并且没有调用useffect
。为了让它发挥作用,我必须像下面这样拆分道具:
const mapStateToProps = (store) => {
return {
// other fields
prop1Errors: store.prop1.errors,
prop2Errors: store.prop2.errors,
prop1Successes: store.prop1.successes,
prop2Successes: store.prop2.successes
}
为什么spread运算符会导致从状态设置过时值,而直接使用状态值则不会
编辑:对于那些感兴趣的人,错误
和成功
的结构如下:
const mapStateToProps = (store) => {
return {
// other fields
errors: {...store.prop1.errors, ...store.prop2.errors},
successes: {...store.prop1.errors, ...store.prop2.errors};
}
errors: {
create: {
error: true,
message: "Error in create"
},
update: {
error: false,
message: ""
}
//... same thing for other actions like fetch, etc
}
//... same thing for successes
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 }}}
}
}
对于reducer代码,它是这样的:
const mapStateToProps = (store) => {
return {
// other fields
errors: {...store.prop1.errors, ...store.prop2.errors},
successes: {...store.prop1.errors, ...store.prop2.errors};
}
errors: {
create: {
error: true,
message: "Error in create"
},
update: {
error: false,
message: ""
}
//... same thing for other actions like fetch, etc
}
//... same thing for successes
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 }}}
}
}
对象初始值设定项中的扩展属性将其自己的可枚举属性从提供的对象复制到新创建的对象上。如果新创建的对象中已存在排列特性,将自动替换该特性 换句话说,如果您有两个对象:
constfoo={a:1}
和constbar={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),
}
}
从这个角度看,你似乎是混合道具到状态,这是一个反模式的反应。也许我弄错了,这只是一个巧合的命名约定。为什么你的约简不能形成你想要的状态对象?你能包括那个代码吗?@DrewReese如果你是指
这个。state
,是的,那是个错误的名字。我会将其更新为store
,意思是Redux商店。不,我指的是您似乎正在状态(或Redux商店,都是应用程序状态)中存储道具的事实。如果没有正确更新/维护,很容易出现过时的问题。如果您总是使用props
中的道具,则不可能发生这种情况(即在消费组件中,道具可能在树中较高的组件中过时)。我认为问题可能在于你的reducer,换句话说,你是如何形成你的state对象的。你能从你的Redux存储中添加代码,以及在设置prop1和prop2的地方添加代码吗?@pranaytripath check edit。prop1和prop2有单独的还原器,代码类似于给定的。替换属性对我来说不是问题。我已确保没有名称冲突的财产;为了方便在子组件中使用,我只需要将所有内容合并为一个。您能给我们展示一下prop1.errors
和prop2.errors
的结构吗?您能给出一个简短的代码示例,说明如何进行深度合并吗?我曾尝试使用Object.keys
和Object.values
复制属性,但没有任何帮助。这是为我准备的;问题中已更新。请注意,我已更新答案,将Object.keys更改为Object.entries。。我的错误