Javascript 推送到useReducer的特定路径处的数组';s州

Javascript 推送到useReducer的特定路径处的数组';s州,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我有一个名为Form的(功能性)组件,在其中我使用useReducer()hook设置一个如下所示的状态: { content: { profile: { firstName: 'John', lastName: 'Doe' }, experiences: [ { employer: 'CompanyX', position: 'CEO' }, { employ

我有一个名为
Form
的(功能性)组件,在其中我使用
useReducer()
hook设置一个如下所示的状态:

{
  content: {
    profile: {
      firstName: 'John',
      lastName: 'Doe'
    },
    experiences: [
      {
        employer: 'CompanyX',
        position: 'CEO'
      },
      {
        employer: 'CompanyY',
        position: 'Intern'
      }
    ]
  }
};
case 'ADD_EXPERIENCE': { 
    return {
        ...state,
        content: {
            ...state.content,
            experiences: [...state.content.experiences, action.newExperience]
        }
    }
}
我想把一个新的经验推到经验数组中,我正在寻找编写我的减速机案例的最佳方法。以下是我提出的解决方案:

// reducer.js

case 'ADD_EXPERIENCE': { 
  newState = _.clone(state);
  newState.content.experiences = _.concat(state.content.experiences, action.newExperience);
  return newState;
}
然而,这在我看来并不优雅。我想知道你们有没有更好的解决办法。例如,lodash的
setWith()
方法是否合适

// reducer.js

case 'ADD_EXPERIENCE': { 
  return _.setWith(
    _.clone(state),
    'content.experiences',
    action.newExperience,
    () => ???
  )
}

您可以使用ES6 spread操作符
来分解状态和新体验数组并返回新状态,如下所示:

{
  content: {
    profile: {
      firstName: 'John',
      lastName: 'Doe'
    },
    experiences: [
      {
        employer: 'CompanyX',
        position: 'CEO'
      },
      {
        employer: 'CompanyY',
        position: 'Intern'
      }
    ]
  }
};
case 'ADD_EXPERIENCE': { 
    return {
        ...state,
        content: {
            ...state.content,
            experiences: [...state.content.experiences, action.newExperience]
        }
    }
}

您可以使用ES6 spread操作符
来分解状态和新体验数组并返回新状态,如下所示:

{
  content: {
    profile: {
      firstName: 'John',
      lastName: 'Doe'
    },
    experiences: [
      {
        employer: 'CompanyX',
        position: 'CEO'
      },
      {
        employer: 'CompanyY',
        position: 'Intern'
      }
    ]
  }
};
case 'ADD_EXPERIENCE': { 
    return {
        ...state,
        content: {
            ...state.content,
            experiences: [...state.content.experiences, action.newExperience]
        }
    }
}
最后:

case 'ADD_EXPERIENCE':
  return _.updateWith(
    _.clone(state),
    'content.experiences',
    (value) => [...value, action.newExperience],
    _.clone
  );
最后:

case 'ADD_EXPERIENCE':
  return _.updateWith(
    _.clone(state),
    'content.experiences',
    (value) => [...value, action.newExperience],
    _.clone
  );

是的,我想过这个。然而,如果state对象变得更深,我的意思是如果它有更多的嵌套,这个解决方案可能会变得单调乏味。此外,它将强制所有组件重新渲染,即使它们侦听的值没有发生变化(如content.profile),也不应将对象与对象、数组与数组进行比较,因为这种比较比较的是指针,而不是值,并且在两个连续渲染之间很少相同。我同意嵌套对象部分,在这种情况下,您的第一个解决方案足够优雅,您可以使用spread运算符或ES6的concat方法,而不是lodash@TheoAvoyne此解决方案保留
state.content.profiles
对象的标识,并且不会重新呈现(仅)依赖该对象的任何已记忆组件,和shallow
一样。clone
是的,我考虑过这个。然而,如果state对象变得更深,我的意思是如果它有更多的嵌套,这个解决方案可能会变得单调乏味。此外,它将强制所有组件重新渲染,即使它们侦听的值没有发生变化(如content.profile),也不应将对象与对象、数组与数组进行比较,因为这种比较比较的是指针,而不是值,并且在两个连续渲染之间很少相同。我同意嵌套对象部分,在这种情况下,您的第一个解决方案足够优雅,您可以使用spread运算符或ES6的concat方法,而不是lodash@TheoAvoyne此解决方案保留
state.content.profiles
对象的标识,并且不会重新呈现(仅)依赖该对象的任何已记忆组件,与浅层
相同。克隆