React-hooks-form - итерация по массиву полей, где одно из полей задается с помощью useState - PullRequest
0 голосов
/ 11 ноября 2019

Я пытаюсь использовать React-hooks-form для создания многошаговой формы, в которой на одном из шагов есть меню выбора, которое предлагает выбор, и два других текстовых поля.

Шаг внутриболее крупная форма имеет:

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, как указано ниже (одинмассив из-за этики и еще один из-за проблем):

"ethics": [
{
"explain": "hel",
"managementPlan": "hello"
},
{
"explain": "hiiii",
"managementPlan": "hi"
}
]
,
"issues": [
{
"value": "withdrawal",
"label": "Right to withdraw"
},
{
"value": "deceptive",
"label": "Deceptive practices"
}
]

Я застрял в этой форме с ошибкой, которая говорит: не могу прочитать карту undefined.

Сообщение об ошибке выделяет проблемууказывая на эту строку:

  {ethics.map((_, index) => {

Я ожидаю, что функция отправки отправит 3 поля формы в одном массиве в updateAction, но этого не происходит, и я не вижу, что мне нужносделать, чтобы это заработало.

Кто-нибудь успешно интегрировал меню выбора с повторяемым полем формы, используя массивы полей в форме реакции-ловушки?

...