Javascript 如何使用useState钩子更新现有的对象数组(向数组中添加新对象)?

Javascript 如何使用useState钩子更新现有的对象数组(向数组中添加新对象)?,javascript,reactjs,typescript,react-redux,react-hooks,Javascript,Reactjs,Typescript,React Redux,React Hooks,我有一个onChange处理程序,可以用它编辑带有输入字段的某些对象 onChange处理程序如下所示: // First I get the current state const [persons, setPersons] = useState(service.persons); <InputWrapper> <TextField type="text" label="Person name"

我有一个onChange处理程序,可以用它编辑带有输入字段的某些对象

onChange处理程序如下所示:

// First I get the current state
const [persons, setPersons] = useState(service.persons);
  <InputWrapper>
    <TextField
      type="text"
      label="Person name"
      name="person_name"
      value=' '
      onChange={e => setNewPerson({ ...newPerson, [e.target.name]: e.target.value })}
    />
  </InputWrapper>
API为人员(对象数组)返回以下内容:

我的onChange处理程序如下所示(…用于编辑给定人员的if语句的第一部分工作正常,但用于创建新人员的else语句工作不正常):

我的模板如下所示(仅空输入字段,用于创建具有person\u公司和person\u姓名的新人员):

但我的目标是,当我创建一个新的人时,对象应该按如下方式更新:

contacts (3) [{…}, {…}, {…}]
0: {person_company: "Google", person_name: "John Doe"}
1: {person_company: "Facebook", person_name: "Jane Doe"}
2: {person_company: "Amazon", person_name: "Max Mustermann"}

我做错了什么?

试试看,不要在对象内部展开列表,而是展开列表并添加对象,这也是因为当你打电话给一个新人时,没有提供索引:

const updatePersons = (e: any, index?: number) => {
  if (index !== undefined) {
    const updatedPersons = [...persons];
    updatedPersons[index][e.target.name] = e.target.value;
    setPersons(updatedPersons.map((person)=>({...person,new:false})));
  } else {
      const lastPerson = persons.slice(-1)[0];
      if (lastPerson.new){
          setPersons([...persons.slice(0,-1), {...lastPerson ,[e.target.name]:e.target.value}]);
      } else {
          setPersons([...persons,{[e.target.name]:e.target.value , new:true}]
      }
   }
};

不幸的是,我无法使用建议的方法解决它。但我用了另一种方式

我修改了updatePersons方法,它现在只处理带有ID的案例(因此不再有其他块)

相反,我现在直接在textfields的onChange处理程序中创建一个新人

// I created another useState hook for the new Person 
// ..and provided an initial state (empty strings) by instantiating a new Person:

const [newPerson, setNewPerson] = useState(new Person());
我的文本字段现在如下所示:

// First I get the current state
const [persons, setPersons] = useState(service.persons);
  <InputWrapper>
    <TextField
      type="text"
      label="Person name"
      name="person_name"
      value=' '
      onChange={e => setNewPerson({ ...newPerson, [e.target.name]: e.target.value })}
    />
  </InputWrapper>

让我知道这个解决方案是否还可以。

使用这种方法,每次击键都会添加一个新对象,在person_company输入字段中键入“test”后,我得到以下结果(并且输入字段中的值仍然没有更新):在调用
onChange={e=>updatePersons(e)}时,还需要提供索引
so
onChange={e=>updatePersons(e,index)}
,或者您需要考虑其他方法来保持“新人”索引,即使在增加列表大小后仍然保持不变,请给它一个快照。如果进展顺利,请通知我。。。很好,幸运的是,这种方法不起作用。但我的解决方法不同——我采用了updatePersons方法,它现在只处理带有ID的案例(因此不再有其他块)。相反,我现在直接在textfields的onChange处理程序中创建一个新人。我还创建了一个submitHandler,在其中更新状态并随后清空表单字段。我将把这个方法作为一个答案。让我知道这个解决方案是否也可以接受。你告诉我们它是否有效……是的,它有效:)。
const updatePersons = (e: any, index?: number) => {
  e.preventDefault(); // is this needed here?
  if (index !== undefined) {
    const updatedPersons = [...persons];
    updatedPersons[index][e.target.name] = e.target.value;
    setPersons(updatedPersons);
  }
};
// I created another useState hook for the new Person 
// ..and provided an initial state (empty strings) by instantiating a new Person:

const [newPerson, setNewPerson] = useState(new Person());
  <InputWrapper>
    <TextField
      type="text"
      label="Person name"
      name="person_name"
      value=' '
      onChange={e => setNewPerson({ ...newPerson, [e.target.name]: e.target.value })}
    />
  </InputWrapper>
  const submitHandler = (e: any) => {
    e.preventDefault(); // is this needed here?
    setPersons([...persons, newPerson]);
    setNewPerson(new Person()); // Empty the form fields
  };