Отправить данные формы в ответ

У меня есть компоненты, в каждом из которых у меня есть одна форма, при нажатии на которую я открываю новую форму (вызывая новый компонент), и когда она последняя, ​​я меняю ее для отправки.

Чего я хочу достичь

1: при каждом следующем и обратном щелчке я хочу проверить свою форму с помощью реакции-формы-хука

2: при нажатии кнопки «Отправить» я должен увидеть все данные

3: при нажатии рядом с задними данные не должны теряться при вводе

Проблема

Поэтому для проверки я использую react-hook-form, так как он очень прост в использовании, но здесь Я не могу узнать, так как мои кнопки не находятся внутри форм, они находятся в основном компоненте, поэтому как я буду проверять и отправлять форму при отправке, щелкая всеми данными.

Мой код

import React, { useState } from "react";
import Form1 from "./components/Form1";
import Form2 from "./components/Form2";
import Form3 from "./components/Form3";

function AddCompanyMain() {
  const [currState, setCurrState] = useState(1);
  const [allState, setAllstate] = useState(3);

  const moveToPrevious = () => {
    setCurrState(currState - 1);
  };
  const moveToNext = () => {
    setCurrState(currState + 1);
  };

  return (
    <div>
      <div class="progress">
        <div>{currState}</div>
      </div>

      {currState === 1 && <Form1 />}
      {currState === 2 && <Form2 />}
      {currState === 3 && <Form3 />}

      {currState !== 1 && (
        <button
          className="btn btn-primary"
          type="button"
          onClick={moveToPrevious}
        >
          back
        </button>
      )}
      {currState !== allState && (
        <button className="btn btn-primary" type="button" onClick={moveToNext}>
          next
        </button>
      )}

      {currState === 3 && (
        <button className="btn btn-primary" type="submit">
          Submit
        </button>
      )}
    </div>
  );
}

export default AddCompanyMain;

Мой полный код песочнице кода

Я просто ищу хороший подход, потому что здесь я не могу поместить отправку в каждый компонент, потому что я должен показывать шаги вверху.


person manish thakur    schedule 07.05.2020    source источник


Ответы (2)


Вы можете решить свою проблему, выполнив следующие действия:

  • В app.js храните формы в массиве объектов и визуализируйте их на основе шага (состояние currentFrom).
  • Вызовите useForm в родительском компоненте (не в дочернем компоненте Form) и передайте register, errors, defaultValues значения в качестве реквизита вашим Form компонентам.
  • В ваших компонентах Form вам нужно использовать register, etc в качестве реквизита.
  • Поддерживайте defaultValues в состоянии и обновляйте их в onClick следующего/предыдущего. Вам нужно getValues, а затем использовать setValues для установки состояния (defaultValues)

Также:

  • Чтобы инициировать проверку при нажатии следующей/предыдущей кнопки, необходимо использовать triggerValidation.

  • Чтобы сохранить значения при нажатии кнопки «Далее/предыдущее», вам необходимо использовать свойство defaultValues.

См. рабочую демонстрацию здесь< /а>

Фрагмент кода

import React, { useState } from "react";
import Form1 from "./components/Form1";
import Form2 from "./components/Form2";
import Form3 from "./components/Form3";
import { useForm } from "react-hook-form";

function AddCompanyMain() {
  const {
    register,
    triggerValidation,
    errors,
    setValue,
    getValues
  } = useForm();
  const [defaultValues, setDefaultValues] = useState({});

  const forms = [
    {
      fields: ["uname"],
      component: (register, errors, defaultValues) => (
        <Form1
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    },
    {
      fields: ["lname"],
      component: (register, errors, defaultValues) => (
        <Form2
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    },
    {
      fields: ["company"],
      component: (register, errors, defaultValues) => (
        <Form3
          register={register}
          errors={errors}
          defaultValues={defaultValues}
        />
      )
    }
  ];

  const [currentForm, setCurrentForm] = useState(0);

  const moveToPrevious = () => {
    setDefaultValues(prev => ({ ...prev, [currentForm]: getValues() }));

    triggerValidation(forms[currentForm].fields).then(valid => {
      if (valid) setCurrentForm(currentForm - 1);
    });
  };

  const moveToNext = () => {
    console.log(getValues());
    setDefaultValues(prev => ({ ...prev, [currentForm]: getValues() }));
    triggerValidation(forms[currentForm].fields).then(valid => {
      if (valid) setCurrentForm(currentForm + 1);
    });
  };

  const prevButton = currentForm !== 0;
  const nextButton = currentForm !== forms.length - 1;

  return (
    <div>
      <div class="progress">
        <div>{currentForm}</div>
      </div>

      {forms[currentForm].component(
        register,
        errors,
        defaultValues[currentForm]
      )}

      {prevButton && (
        <button
          className="btn btn-primary"
          type="button"
          onClick={moveToPrevious}
        >
          back
        </button>
      )}
      {nextButton && (
        <button className="btn btn-primary" type="button" onClick={moveToNext}>
          next
        </button>
      )}

      {currentForm === 3 && (
        <button className="btn btn-primary" type="submit">
          Submit
        </button>
      )}
    </div>
  );
}

export default AddCompanyMain;

Примечание. Как правило, при работе с многошаговыми формами лучше использовать контролируемые компоненты и сохранять состояния в родительском компоненте.

person gdh    schedule 11.05.2020
comment
Эй, ваше решение в порядке, если каждая форма имеет одно поле ввода здесь, в моем случае у меня есть несколько полей ввода в каждой форме, предположим, например, у меня есть 2 ввода в моей форме, один, и т.е. возраст, поэтому в основных компонентах в массиве полей я передавая второе значение, то есть возраст, поэтому он работает нормально, но когда я возвращаюсь, то есть от 2 до 1, значения, которые принимают оба поля ввода, одинаковы, то есть все, что я передаю в вашем имени, возраст принимает то же самое. - person manish thakur; 11.05.2020
comment
ммм... дай мне коды и ячейку, где ты указал возраст, я исправлю - person gdh; 11.05.2020
comment
codesandbox.io/s/determined-glade-ei1in?file =/src/App.js Эй, вот моя песочница кода, возраст, который я только что взял, например, главное, что формы могут иметь несколько полей, ни одна из форм не будет иметь одно поле. - person manish thakur; 11.05.2020
comment
только что проверил - в вашем примере uname и age принимают одинаковые значения, потому что вы неправильно установили возраст defaultValue. то есть вы использовали defaultValues.uname вместо .age. Итак, для ввода возраста сделайте defaultValue={defaultValues && defaultValues.age}... надеюсь, теперь все хорошо... - person gdh; 12.05.2020
comment
Эй, я не получил ваше решение, не могли бы вы поделиться ссылкой codesandbox. - person manish thakur; 12.05.2020
comment
здесь codesandbox.io/s/cocky-fire-8xsz0 ... в основном, в Form1, в строке 25 вместо defaults.uname сделать defaultValues.age - person gdh; 12.05.2020
comment
эй, при отправке, я хочу, чтобы все данные моих форм, такие как uname: test, age: 22 ... теперь, где я должен сделать <form onSubmit={handleSubmit(onSubmit)}>, чтобы обработать отправку - person manish thakur; 12.05.2020
comment
defaultValues будет иметь все данные вашей формы ..... так что есть кнопка onClick on Submit в App.js и просто получить ее из состояния ... я обновил код ... обновите ту же ссылку на песочницу ... - person gdh; 12.05.2020
comment
это просто... используйте { ...defaultValues, [currentForm]: getValues() } в handleSubmit, вы получите полные данные формы... я обновил код в песочнице... используйте ту же ссылку - person gdh; 12.05.2020
comment
Эй, не могли бы вы помочь мне с некоторым подходом к этому stackoverflow.com/questions/63814645/ Я уже давно застрял здесь - person manish thakur; 10.09.2020

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

import React from "react";
import "./styles.css";

const FormOne = ({ value, onChange }) => (
  <div>
    Form 1
    <input type='text' value={value} onChange={e => onChange(e.target.value)} />
  </div>

)

const FormTwo = ({ value, onChange }) => (
  <div>
    Form 2
    <input type='text' value={value} onChange={e => onChange(e.target.value)} />
  </div>
)

const FormThree = ({ value, onChange }) => (
  <div>
    Form 3
    <input type='text' value={value} onChange={e => onChange(e.target.value)} />
  </div>
)

export default function App() {
  const [formOne, setFormOne] = React.useState('')
  const [formTwo, setFormTwo] = React.useState('')
  const [formThree, setFormThree] = React.useState('')
  const [index, setIndex] = React.useState(0)

  const moveUp = (e) => {
    e.preventDefault()

    if (index !== 2) {
      setIndex(index => index += 1)
    }
  }

  const moveDown = (e) => {
    e.preventDefault()

    if (index !== 0) {
      setIndex(index => index -= 1)
    }
  }

  const handleSubmit = (e) => {
    e.preventDefault()

    console.log(formOne, formTwo, formThree)
  }

  const form = index === 0
    ? <FormOne value={formOne} onChange={setFormOne} />
    : index === 1
    ? <FormTwo value={formTwo} onChange={setFormTwo} />
    : <FormThree value={formThree} onChange={setFormThree} />

  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        {form}
        {index !== 0 && <button onClick={moveDown}>Back</button>}
        {index !== 2
          ? <button onClick={moveUp}>Next</button>
          : <button type='submit'>Submit</button>
        }
      </form>
    </div>
  );
}
person adrianp    schedule 07.05.2020
comment
Проверьте редактирование. Здесь нужно сделать много оптимизаций, но это должно помочь вам начать. - person adrianp; 07.05.2020
comment
Не могли бы вы предоставить рабочую демонстрацию? - person walee; 05.04.2021