如何使用 useState 在 React Typescript 中推送嵌套对象接口数组

How to push nested object interface array in React Typescript using useState

界面

  interface ListInterface {
    listName: string;
    list: string[];
  }

useState

  const [initialList, setinitialList] = useState<ListInterface>({listName: "List1", list:['One', 'Two', 'Three', 'Four', 'Five', 'Six']});
  const [selectedList, setSelectedList] = useState<ListInterface>(initialList);

我知道如何向数组添加新元素(推送)。但是当数组在 object/inteface 中时会遇到麻烦。你是如何使用 useState 挂钩的?

setTheArray(oldArray => [...oldArray, newElement]);

我创建了一个简单的沙箱示例。

https://codesandbox.io/s/reacr-ts-nested-object-array-example-z1uyd?file=/src/App.tsx

您已经定义了一个对象接口,这意味着您需要在每次更新时推送一个符合该类型的对象。

  
  // ...

  const [text, setText] = useState<string>(''); // <--- set type and set to blank to remove type errors due to `text` being possibly undefined

  // ...

  const handleSubmit = (event: any) => {    
    event.preventDefault();
    console.log("Submitted: " + text);

    //setSelectedList({list: oldArray => [...oldArray, newElement]});
    // the above wont work because it is an array, but `ListInterface` is an object (you might want to change the name to `ListEntry` or `ListObject` to avoid confusion)

    setSelectedList({
      listName: selectedList.listName,
      list: [...selectedList.list, text]
    })

  };

感谢接受。也请查看@axtck 的回答,因为他们对您的代码进行了其他一些重要改进!

您不应该为您的初始对象初始化状态变量,您可以只使用接口并以这种方式声明它:

const initialList: ListInterface = {
  listName: "List1",
  list: ["One", "Two", "Three", "Four", "Five", "Six"]
};

因为你只想更新对象内部的列表,你可以这样使用functional setState()

const handleSubmit = (event: any) => {
  console.log("Submitted: " + text);
  event.preventDefault();

  setSelectedList((prevState) => {
    return { ...prevState, list: prevState.list = [...prevState.list, text] };
  });
};

mapping 时,请确保您传递了有效的 key:

{selectedList.list.map((item, i) => {
  return <h3 key={i}>{item}</h3>;
})}

完整代码并已更新 sandbox

import { useState } from "react";
import "./styles.css";

export default function App() {
  interface ListInterface {
    listName: string;
    list: string[];
  }

  const initialList: ListInterface = {
    listName: "List1",
    list: ["One", "Two", "Three", "Four", "Five", "Six"]
  };

  const [selectedList, setSelectedList] = useState<ListInterface>(initialList);
  const [text, setText] = useState("");

  const handleChange = (event: any) => {
    setText(event.target.value);
  };

  const handleSubmit = (event: any) => {
    console.log("Submitted: " + text);
    event.preventDefault();

    setSelectedList((prevState) => {
      return { ...prevState, list: prevState.list = [...prevState.list, text] };
    });
  };

  return (
    <div className="App">
      {selectedList.list.map((item, i) => {
        return <h3 key={i}>{item}</h3>;
      })}

      <form onSubmit={handleSubmit}>
        <label>
          Add To List:
          <input type="text" value={text} onChange={handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    </div>
  );
}