首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React-hooks-form -迭代字段数组,其中一个字段是使用useState设置的

React-hooks-form -迭代字段数组,其中一个字段是使用useState设置的
EN

Stack Overflow用户
提问于 2019-11-11 08:22:01
回答 1查看 5.6K关注 0票数 2

我正在尝试使用React-hooks-form构建一个多步骤表单,其中一个步骤有一个提示选择的选择菜单和另外两个文本字段。

较大表单中的步骤包括:

代码语言:javascript
复制
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import useForm from "react-hook-form";
import { withRouter } from "react-router-dom";
import { useStateMachine } from "little-state-machine";
import updateAction from "./updateAction";
import { Form, Button, Divider, Layout, Typography, Skeleton, Switch, Card, Icon, Avatar } from 'antd';
import Select from "react-select";



const { Content } = Layout 
const { Text, Paragraph } = Typography;
const { Meta } = Card;





const defaultValue = {
  explain: "",
  managementPlan: ""
};

const issueOptions = [
  { value: "riskofharm", label: "Risk of harm" },
  { value: "informedconsent", label: "Informed consent" },
  { value: "anon", label: "Anonymity and Confidentiality" },
  { value: "deceptive", label: "Deceptive practices" },
  { value: "withdrawal", label: "Right to withdraw" },
  { value: "none", label: "No ethics considerations" }
];

const Budget = props => {
  const [ethics, setEthics] = useState([]);
  const [issues, setIssues] = useState([]);
  const { action } = useStateMachine(updateAction);
  const { register, handleSubmit, setValue, getValues, clearError } = useForm();

  useEffect(() => {
    register({ name: "issues" });
  }, [register]);

  // const onSubmit = data => {
  //   console.log("submit", data);
  const onSubit = data => {
    // console.log("submit", data);
    // console.log("combined", formValues);


    // combine your ethicsIssue to formValues
    const { ethics, issues } = data;
    const formValues = {
      ethics: ethics.map((ethic, index) => ({
        ...ethic,
        issue: issues[index]
      }))
    };
    action(data);
    props.history.push("./ProposalOutcomes");

  };               



  const handleChange = index => selectecIssue => {
    const issuesCopy = [...issues];
    issuesCopy[index] = selectecIssue;

    setIssues(issuesCopy);
    setValue("issues", issuesCopy);
  };

  const addEthic = async () => {
    setEthics([...ethics, defaultValue]);
  };

  const removeEthic = index => () => {
    // get values
    const { ethics, issues } = getValues({ nest: true });

    // create a copy
    const newEthics = [...(ethics || [])];
    const newIssues = [...(issues || [])];

    // remove by index
    newEthics.splice(index, 1);
    newIssues.splice(index, 1);

    // update values
    setEthics(newEthics);
    setIssues(newIssues);

    for (let i = 0; i < newEthics.length; i++) {
      // we register the field using ethics[i].explain
      // therefore, we need to setValue that way
      setValue(`ethics[${i}].explain`, newEthics[i].explain);
      setValue(`ethics[${i}].managementPlan`, newEthics[i].managementPlan);
    }

    // same goes with issue
    setValue("issues", newIssues);
  };

  const clearEthics = () => {
    setEthics([]);
    setIssues([]);
    setValue("issues", []);
    clearError();
  };

  return (
    <div>
      <Content
        style={{
          background: '#fff',
          padding: 24,
          margin: "auto",
          minHeight: 280,
          width: '70%'
        }}
      >
      <Paragraph>
        <h2>Design Studio</h2>
        <h4 style={{ color: '#506e8d'}}>Design a Research Proposal</h4>
        </Paragraph>
        <Divider />

        <h2>Part 10: Ethics</h2>


    <form onSubmit={handleSubmit(onSubit)}>
      {ethics.map((_, index) => {
        const fieldName = `ethics[${index}]`;

        return (
          <fieldset name={fieldName} key={fieldName}>
            <label>
              Issue {index}:
              <Select
                placeholder="Select One"
                value={issues[index]}
                options={issueOptions}
                onChange={handleChange(index)}
              />
            </label>

            <label>
              Explain {index}:
              <input type="text" name={`${fieldName}.explain`} ref={register} />
            </label>

            <label>
              Management Plan {index}:
              <input
                type="text"
                name={`${fieldName}.managementPlan`}
                ref={register}
              />
            </label>

            <Button type="danger" style={{ marginBottom: '20px', float: 'right'}} onClick={removeEthic(index)}>
              Remove Ethic
            </Button>
          </fieldset>
        );
      })}
      <div className="action">
        <Button type="primary" style={{ marginBottom: '20px'}} onClick={addEthic}>
          Add Ethic
        </Button>
        <br />
        <Button type="button" style={{ marginBottom: '20px'}} onClick={clearEthics}>
          Clear Ethics
        </Button>
      </div>
      <input type="submit" value="next - outcomes" />

    </form>
    </Content>
    </div>
  );
}



export default withRouter(Budget);

我在生成一个包含3个字段中的内容的数组时遇到了问题。

目前,我得到了如下所示的json包(一个数组涉及道德规范,另一个涉及问题):

代码语言:javascript
复制
"ethics": [
{
"explain": "hel",
"managementPlan": "hello"
},
{
"explain": "hiiii",
"managementPlan": "hi"
}
]
,
"issues": [
{
"value": "withdrawal",
"label": "Right to withdraw"
},
{
"value": "deceptive",
"label": "Deceptive practices"
}
]

我在这个表单上遇到了一个错误:无法读取未定义的映射。

错误消息突出显示指向以下行的问题:

代码语言:javascript
复制
  {ethics.map((_, index) => {

我期望on submit函数将单个数组中的3个表单域推送到updateAction,但这并没有发生,我也看不出需要做些什么才能让它正常工作。

有没有人使用react-hook-forms中的字段数组成功地将选择菜单与可重复的表单字段集成在一起?

EN

回答 1

Stack Overflow用户

发布于 2020-01-10 18:48:45

我已经为Field Array添加了一个新的部分,我们还在为useFieldArray开发一个新的自定义钩子。https://react-hook-form.com/advanced-usage#FieldArrays

下面是一个代码片段:

代码语言:javascript
复制
import React, { useState } from "react";
import { useForm } from "react-hook-form";

function createArrayWithNumbers(length) {
  return Array.from({ length }, (_, k) => k + 1);
}

export default function App() {
  const { register, handleSubmit } = useForm();
  const [size, setSize] = useState(1);
  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {createArrayWithNumbers(size).map(index => {
        return (
          <>
            <label htmlFor="firstName">First Name</label>
            <input
              name={`firstName[${index}]`}
              placeholder="first name"
              ref={register({ required: true })}
            />

            <label htmlFor="lastName">Last Name</label>
            <input
              name={`lastName[${index}]`}
              placeholder="last name"
              ref={register({ required: true })}
            />
          </>
        );
      })}

      <button type="button" onClick={() => setSize(size + 1)} >
        Add Person
      </button>

      <input type="submit" />
    </form>
  );
}

此codesandbox还显示了高级用法:https://codesandbox.io/s/react-hook-form-field-array-advanced-with-delete-insert-append-edit-l19pz

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58794181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档