[React] useContext를 활용한 Dynamic Form

jiseong·2022년 1월 13일
0

T I Learned

목록 보기
167/291

Dynamic Form

input tag가 늘어나도 적용될 수 있는 form 작성
// useRef를 이용해서 이렇게도 작성할 수 있다 ㄷ ㄷ;;
// 참고해서 앞으로 하는 프로젝트에 적용해보기

// FormContext.js
import { useRef, useCallback, useContext, createContext } from "react";

const FormContext = createContext(null);
    
function useForm() {
  const formRef = useRef({});
  
  const handleSubmit = useCallback(
    (callback) => (e) => {
      e.preventDefault();      
      callback(formRef.current);
    },
    [formRef.current]
  );

  const register = useCallback(
    (label) => {
        console.log('등록된 라벨 : ', label)
        const onChange = e => {
          formRef.current = {
            ...formRef.current,
            [label]: e.target.value
          }
        }
        
        return {
          onChange,
          name: label
        }
        
    },
    []
  );

  return { register, handleSubmit };
}

export function useFormContext() {
  const context = useContext(FormContext);
  if (!context) {
    throw new Error("Use FormContext inside provider.");
  }
  return context;
}

export function FormProvider({ children }) {
  const formControls = useForm();

  return (
    <FormContext.Provider value={formControls}>{children}</FormContext.Provider>
  );
}
// Form.js
import React from "react";
import { useFormContext } from "./FormContext";

export function Form({ children, onSubmit }) {
  const { handleSubmit } = useFormContext();
  return <form onSubmit={handleSubmit(onSubmit)}>{children}</form>;
}

export function TextInput({ label, ...props }) {
  const { register } = useFormContext();
  return <input type="text" {...register(label)} {...props} />;
}

export function SubmitButton({ children }) {
  return <button type="submit">{children}</button>;
}
import React, { useState, useCallback } from "react";
import { FormProvider } from "./FormContext";
import { Form, TextInput, SubmitButton } from "./Form";

export default function DynamicFormApp() {
  const [result, setResult] = useState(undefined)
  const handleSubmit = useCallback((data) => {
    setResult(data)
  }, []);

  return (
  <>
    <FormProvider>
      <Form onSubmit={handleSubmit}>
        <TextInput label="test-input-1" placeholder="Test input." />
        <TextInput label="test-input-2" placeholder="Test input." />
        <TextInput label="test-input-3" placeholder="Test input." />
        <TextInput label="test-input-4" placeholder="Test input." />
        <SubmitButton>Submit</SubmitButton>
      </Form>
    </FormProvider>
    {result && (
        <pre>
            <code>{JSON.stringify(result, null, 2)}</code>
        </pre>
    )}
  </>
  );
}

0개의 댓글