ABOUT ME

개발에 대한 내용을 주로 기록하고, 그 외에 남기고 싶은 것들을 기록합니다.

Today
Yesterday
Total
  • [React] react-hook-form(feat. typescript)으로 Input 컴포넌트 만들어보기
    프레임워크/React(NextJs) 2022. 9. 6. 21:41

    이 글은 프로젝트의 파일 구조와 디자인패턴을 고민하면서 시도했던 방법을 작성해두기 위한 글입니다.

    해당 코드는 현재 사용하는 방식일 수도, 아닐 수도 있습니다.

    이런식으로 코드를 짜봤구나. 정도의 예시로 봐주시면 감사하겠습니다.

     

     

     

    사용한 라이브러리 : react-hook-form

     

     

    ./src/components/forms/Form.tsx

    import * as React from 'react';
    
    interface onSubmitProps {
      onSubmit: React.FormEventHandler;
      children: React.ReactNode;
    }
    
    const Form = ({ onSubmit, children }: onSubmitProps) => {
      return <form onSubmit={onSubmit}>{children}</form>;
    };
    
    export default Form;

     

     

    ./src/components/forms/InputText.tsx

    import * as React from 'react';
    import { ChangeHandler } from 'react-hook-form';
    
    interface FormRegister {
      name: string;
      ref: React.Ref<any>;
      onChange?: ChangeHandler;
      onBlur?: ChangeHandler;
    }
    
    export interface InputTextProps {
      type: 'text' | 'email' | 'password';
      defaultValue?: string;
      placeholder?: string;
      formRegister?: FormRegister;
    }
    
    const InputText = ({ type, defaultValue, placeholder, formRegister }: InputTextProps) => {
      return (
        <input type={type} defaultValue={defaultValue} placeholder={placeholder} {...formRegister} />
      );
    };
    
    export default InputText;

     

    ./src/components/forms/SubmitButton.tsx

    interface SubmitButtonProps {
      value: string;
    }
    
    const SubmitButton = ({ value }: SubmitButtonProps) => {
      return <input type="submit" value={value} />;
    };
    
    export default SubmitButton;

     

     

    ./src/components/list/InputCard.tsx

    import { useForm } from 'react-hook-form';
    
    import Form from '../forms/Form';
    import InputText from '../forms/InputText';
    import SubmitButton from '../forms/SubmitButton';
    
    export interface FormType {
      content: string;
    }
    
    const InputCard = ({ content }: FormType) => {
      const { handleSubmit, register } = useForm<FormType>();
      
      const submitHandler = handleSubmit((data) => console.log(data));
    
      return (
        <Form onSubmit={submitHandler}>
          <InputText
            type="text"
            formRegister={register('content')}
            defaultValue={content}
            placeholder="데이터를 입력해주세요"
          />
          <SubmitButton value="저장" />
        </Form>
      );
    };
    
    export default InputCard;

     

    일단 type="text"를 기준으로 만든 컴포넌트인데, input 태그에는 타입이 많다.

    그래서 그중에서 text, email, password, mobile, ... 등은 같은 컴포넌트로 묶을 수 있을 것 같고,

    number는 조금 더 생각해봐야할 것 같고.. (onSubmit했을 때 string값으로 뽑아낼 수 있긴한데, input 모양이 조금 달라서..)

    file이나 checkbox, radio는 너무 다르니까 각각 컴포넌트를 만들어야할 것 같다.

     

     

    음.. 아니면 아래 포스팅 내용에 있는 예시 처럼 컴포넌트를 객체화 시켜서 관리하면 편할지도?

    https://javascript.plainenglish.io/5-advanced-react-patterns-a6b7624267a6

     

    <Counter.Decrement />
    <Counter.Label />

     

    이렇게 예시 있는 것 처럼 아래와 같이 만드는 것도 고려해보자

    <Input.text />
    <Input.file />
    <Input.Radio />

     

     

    그리고 추가적으로 InputCard 는 좀 더 분리가 필요함.

    submitHandler이 저렇게 들어가면 view와 비즈니스 로직이 구분이 안된 것.

    handleSubmit안에 있는 function을 props로 넘겨받는 쪽으로 수정해서 사용하기 🙌

    onSubmit에 동작할 함수는 이 컴포넌트를 사용하는 페이지에서 선언하는 걸로!

     

     

     

    갑자기 든 생각인데, input도 HTML태그 중에 컴포넌트화 된거라고 할 수 있으려나..? ㅎ

    그렇다면 하나의 태그에 너무 많은 기능을 넣은 걸지도.. select box처럼 따로 뺐어야 하는게 아닐까?

    댓글

Designed by Tistory.