How to combine form using React Js? [Snippet Attached]

烈酒焚心 提交于 2021-02-08 12:11:09

问题


I am trying to make a form in reactjs like this https://jsonresume.org/schema/ (JSON Format).

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;

Compenents such as <BasicDetails /> and <EmploymentDetails /> code can be found in attached codesandbox.

Here I have made the form to have a separate components for each like,

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

Requirement:

I am in the need to combine these inputs in a single json format like this

For now I have basic details and employment details which is in different files So how can I combine these two files/components to form a complete JSON?

Expected JSON format on click of the submit button (index.js):

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

Look at the below codesandbox that has the JSON format of input fields in respective component. I am in the need to combine those and display final form on click of submit button.

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

Note: The component sections will keep on increasing like we will add new components like skills, education details (not added here but will add in future) etc.., so kindly provide the solution accordingly.

A big thanks in advance..


回答1:


This can be done using Context API. The idea is to have your state shared across multiple components.

The code below will hold a formValue that will be accessed on EmploymentDetails and BasicDetails components.

// 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>
  );
}

On your BasicDetails, you access the formValue state above through

// 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 };
    });
  };

  ...
};

- also notice how we implement our handleInputChange, we're updating the formValue using setValue coming from our FormContext.

Check the demo, and ask me if you want to clarify anything. Read Context docs here.




回答2:


Here is a possible solution. I only coded basicDetails but principle is the same for the remaining fields:

  1. you have to handle changes from child components to parent component using fieldChange props:
    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. keep changes in your parent component state:
    <BasicDetails fieldChange={(value) => setBasicDetails(value)} />

Another solution would have been useForm, depending on your project complexity



来源:https://stackoverflow.com/questions/63594695/how-to-combine-form-using-react-js-snippet-attached

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!