javascript 在react-router-dom v6中使用表单和动作的动态输入字段

aoyhnmkz  于 2023-10-14  发布在  Java
关注(0)|答案(1)|浏览(102)

我刚开始使用新的react router dom表单和动作。有静态输入的范式工作正常吗?我想知道如何使输入字段动态化。例如,对于一个特定的领域,如何进行多项输入,我想从用户那里获得兴趣。现在用户可以有多个兴趣,所以他应该有一个选项来添加另一个兴趣领域。基本上,这就是我想从用户那里得到的:

data={
  name:'name goes here',
  password:'password',
  interest:["interest one","interest two", "interest three"]
}

现在主要的事情是想做它使用的形式和行动的react-router-dom和FormData API。以下是我到目前为止的实现:

import { Form } from "react-router-dom";
import { useState } from "react";

export const action = async ({ request }) => {
  const formData = await request.formData();
  console.log(formData);
  const data = Object.fromEntries(formData);
  console.log(data);
  return data;
};

export default function Home() {
  const [interests, setInterests] = useState([{ val: "" }]);

  const handleFormChange = (event, index) => {
    let data = [...interests];
    data[index][event.target.name] = event.target.value;
    setInterests(data);
  };

  const addFields = () => {
    let object = {
      name: "",
      age: ""
    };

    setInterests([...interests, object]);
  };
  const removeFields = (index) => {
    let data = [...interests];
    data.splice(index, 1);
    setInterests(data);
  };
  return (
    <div>
      <Form method="post" className="form">
        <input type="text" name="username" placeholder="username" />
        <input type="password" name="password" placeholder="password" />
        {interests.map((item, index) => (
          <div key={index}>
            <input
              type="text"
              name="val"
              placeholder="interests"
              onChange={(event) => handleFormChange(event, index)}
              value={item.val}
            />

            <button onClick={() => removeFields(index)}>Remove</button>
          </div>
        ))}
        <button type="button" onClick={addFields}>
          Add More..
        </button>

        <button type="submit"> Submit</button>
      </Form>
    </div>
  );
}

但是当我控制数据时,我只得到了名称、密码和一个感兴趣的值。此外,如果我添加另一个字段并开始在该字段中写入,它会显示此警告:A component is changing an uncontrolled input to be controlled.这里是代码沙箱链接也https://codesandbox.io/s/naughty-chebyshev-yyznl3?file=/src/Home.jsx:0-1563

agxfikkp

agxfikkp1#

给予每个“兴趣”输入一个唯一的name属性。例如,合并“利益”与当前数组索引。

const handleFormChange = (event, index) => {
  setInterests((interests) =>
    interests.map((interest, i) =>
      i === index ? { val: event.target.value } : interest
    )
  );
};
{interests.map((item, index) => (
  <div key={index}>
    <input
      type="text"
      name={`interests-${index}`}
      placeholder="interests"
      onChange={(event) => handleFormChange(event, index)}
      value={item.val}
    />

    <button onClick={() => removeFields(index)}>Remove</button>
  </div>
))}

如果您想将兴趣提取回一个数组中,您可以Map表单数据并搜索"interests-*"键,然后将值缩减到一个数组中。

export const action = async ({ request }) => {
  const formData = await request.formData();
  const data = Object.fromEntries(formData);

  const interests = Object.entries(data).reduce((interests, [key, value]) => {
    const [interestsKey] = key.split("-");
    if (interestsKey === "interests") {
      interests.push(value);
    }
    return interests;
  }, []);

  ...

  return data;
};

此外,如果我添加另一个字段并开始在该字段中写入,它会显示此警告:“某个组件正在更改要控制的非受控输入。”
这是因为被Map的interests状态需要具有val属性的数组元素对象,但是addFields函数添加了仅具有nameage属性的对象。添加val作为已定义的属性,以便新输入具有已定义的value属性。

const addFields = () => {
  setInterests((interests) => interests.concat({ val: "" }));
};

相关问题