如何设置嵌套后坐状态?

How can I set a nested recoil state?

我有一个嵌套的计划列表。我想添加计划并使用后坐力显示它。但是我不需要添加name属性,只需要输入plan即可。

import React, { useState } from "react";
import "./styles.css";
import { RecoilRoot, atom, useRecoilState } from "recoil";

const todoListState = atom({
  key: "TodoList",
  default: {
    name: "Lee",
    plans: [
      {
        plan: "",
        price: ""
      }
    ]
  }
});

export function TodoApp() {
  const [list, setList] = useRecoilState(todoListState);
  const [input, setInput] = useState({
    plan: "",
    price: ""
  });

  const handleChange = (e) => {
    setInput({
      ...input,
      [e.target.name]: e.target.value
    });
  };

  const handleClick = async (e) => {
    e.preventDefault();
    setList({
      plan: input.plan,
      price: parseInt(input.price)
    });
    setInput({
      plan: "",
      price: ""
    });
  };

  return (
    <>
      <div>Plans</div>
      {list.plans.map((x, i) => {
        return (
          <div key={i}>
            <div>{x.plan}</div>
            <div>{x.price}</div>
          </div>
        );
      })}
      <div>
        <label htmlFor="plan">plan</label>
        <input
          type="text"
          value={input.plan}
          onChange={handleChange}
          name="plan"
        />
      </div>
      <div>
        <label htmlFor="price">price</label>
        <input
          type="text"
          value={input.price}
          onChange={handleChange}
          name="price"
        />
      </div>
      <button onClick={handleClick}>Add Item</button>
    </>
  );
}

export default function App() {
  return (
    <RecoilRoot>
      <div className="App">
        <TodoApp />
      </div>
    </RecoilRoot>
  );
}

要实现这个,我需要使用或修复什么? 代码如下:

https://codesandbox.io/embed/nested-arrays-forked-49idv?fontsize=14&hidenavigation=1&theme=dark

您只需要重构您的点击处理程序,这样当您更新您的反冲原子时,您就可以散布在对象的现有部分中,有效地附加到数组中:

const handleClick = async (e) => {
  e.preventDefault();

  setList(list => ({
    ...list,
    plans: [
      ...list.plans,
      {
        plan: input.plan,
        price: parseInt(input.price),
      },
    ],
  }));

  setInput({plan: "", price: ""});
};