Как объединить форму с помощью React Js? [Фрагмент прилагается]

#javascript #json #reactjs #forms #next.js

#javascript #json #reactjs #формы #next.js

Вопрос:

Я пытаюсь создать форму в reactjs следующим образомhttps://jsonresume.org/schema / (Формат JSON).

index.js:

 import React, { useState, Fragment } from 'react';
import BasicDetails from '../components/basic_details';
import EmploymentDetails from '../components/employment_details';

const App = () => {
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('get the whole form json here');
  };

  return (
    <>
      <h1>Dynamic Form Fields in React</h1>
      <form onSubmit={handleSubmit}>
        Basic Details:
        <br />
        <hr />
        <BasicDetails />
        <br />
        <br />
        Employment Details:
        <br />
        <hr />
        <EmploymentDetails />
        <div className="submit-button">
          <button
            className="btn btn-primary mr-2"
            type="submit"
            onSubmit={handleSubmit}
          >
            Save
          </button>
        </div>
        {/* <pre>{JSON.stringify(inputFields, null, 2)}</pre> */}
      </form>
    </>
  );
};

export default App;
  

Такие компоненты, как <BasicDetails /> и <EmploymentDetails /> code, можно найти в прилагаемом codesandbox.

Здесь я создал форму, чтобы иметь отдельные компоненты для каждого подобного,

 ---> Basic Details
---> Employment Details
---> ...So on ...
  

Требование:

Мне необходимо объединить эти входные данные в единый формат json вот так

На данный момент у меня есть основные сведения и сведения о занятости, которые находятся в разных файлах, так как я могу объединить эти два файла / компонента, чтобы сформировать полный JSON?

Ожидаемый формат JSON при нажатии кнопки отправки (index.js ):

 {
  "basicDetails": {
    "firstName": "John",
    "lastName": "Doe"
  },
  "companyDetails": [{
     "companyName": "xyz",
     "designation": "lmn"
   },
   {
     "companyName": "abc",
     "designation": "def"
   }
 ]
}
  

Посмотрите на приведенный ниже codesandbox, который имеет формат полей ввода JSON в соответствующем компоненте.
Мне нужно объединить их и отобразить окончательную форму нажатием кнопки отправки.

Codesandbox: https://codesandbox.io/s/next-dynamic-testing-issue-forked-ieqf5

Примечание: Разделы компонентов будут продолжать увеличиваться, поскольку мы будем добавлять новые компоненты, такие как навыки, сведения об образовании (не добавлены здесь, но будут добавлены в будущем) и т.д., Поэтому, пожалуйста, предоставьте соответствующее решение.

Заранее большое спасибо..

Ответ №1:

Это можно сделать с помощью Context API. Идея в том, чтобы ваше состояние было общим для нескольких компонентов.

Приведенный ниже код будет содержать a, formValue к которому будут доступны компоненты EmploymentDetails и BasicDetails .

 // components/form_context.js

import React, { useState } from 'react';

export const FormContext = React.createContext();

export function FormProvider({ children }) {
  const [formValue, setFormValue] = useState({
    basicDetails: {
      firstName: '',
      lastName: '',
    },
    companyDetails: [
      {
        companyName: '',
        designation: '',
      },
    ],
  });

  return (
    <FormContext.Provider value={[formValue, setFormValue]}>
      {children}
    </FormContext.Provider>
  );
}
  

На вашем BasicDetails компьютере вы получаете доступ к formValue состоянию, указанному выше, через

 // components/basic_details.js

import { FormContext } from './form_context';

const BasicDetails = () => {
  const [value, setValue] = React.useContext(FormContext); // here
  const { basicDetails } = value;

  const handleInputChange = (event) => {
    const { name, value } = event.target;
    setValue((prev) => {
      const basicDetails = { ...prev.basicDetails, [name]: value };
      return { ...prev, basicDetails };
    });
  };

  ...
};
  

— также обратите внимание, как мы реализуем наше handleInputChange , мы обновляем formValue использование setValue , исходящее из нашего FormContext .

Проверьте демонстрацию и спросите меня, хотите ли вы что-нибудь уточнить. Прочитайте Context документы здесь.

Редактировать следующую проблему динамического тестирования (разветвленную)

Комментарии:

1. Это решение сейчас выглядит для меня нормально.. Я приму это сейчас, и если у меня возникнут какие-либо проблемы, я свяжусь с вами.. Спасибо..

2. Конечно, просто дай мне знать, np.

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

4. Конечно, какие данные вы хотите проверить?

5. Спасибо.. Поля имен (имя, фамилия и поле для обозначения сведений о компании) не должны принимать цифры.. Затем firstname в основных деталях и в сведениях о компании должно быть обязательно поле ввода company name и designation ..

Ответ №2:

Вот возможное решение. Я только закодировал базовые данные, но принцип тот же для остальных полей:

  1. вы должны обрабатывать изменения от дочерних компонентов к родительскому компоненту с помощью реквизитов fieldChange:
     const BasicDetails = ({ fieldChange }) => {
    
    ...
    
      const handleInputChange = (event) => {

        if (event.target.name === 'firstName') {
          setInputField({ ...inputField, firstName: event.target.value });
        } else {
          setInputField({ ...inputField, lastName: event.target.value });
        }
        fieldChange(inputField);
      };
  
  1. сохраняйте изменения в состоянии вашего родительского компонента:
     <BasicDetails fieldChange={(value) => setBasicDetails(value)} />
  

Другим решением было бы использовать форму, в зависимости от сложности вашего проекта

Комментарии:

1. Спасибо за ваш ответ.. Но мой ожидаемый результат — это объединение основных сведений и сведений о компании и отображение их в едином формате json при нажатии кнопки отправки..

2. Кроме того, ваш ответ просто печатает объект таким, какой он есть {firstName: "John", lastName: "Doe"} в то время как мой ожидаемый результат { "basicDetails": { "firstName": "John", "lastName": "Doe" }