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。。我的错误