[React] 클린 코딩을 하자!

Ell!·2021년 11월 24일
0

react

목록 보기
9/28

Form 형태를 cleanCoding

오늘 작업은 비밀번호 reset form이었다.
그동안 너무 막 그때그때 필요한 컴포넌트를 만들면서 했는데, 이번 기회에 재사용 가능하게 만들어보고 싶어서 그리했고, 마음에 드는 결과물이 나온 것 같아서 자랑(?)해본다.


// form의 textfield 등의 input 재사용

import React, { createElement } from 'react';
import PropTypes from 'prop-types';
import { Controller } from 'react-hook-form';
import { ErrorMessage } from '@hookform/error-message';
import ReactCodeInput from 'react-code-input';
import { TextField, InputLabel } from '@material-ui/core';
import { Container } from './styles';

// 부모 컴포넌트에서 useForm을 정의해서 control, errors 등을 내려준다.
const ControlledInput = ({
  control,
  name,
  rules,
  errors,
  defaultValue,
  renderComponent,
  inputLabel,
  componentProps,
  ...arg
}) => {
  
  const COMPONENT_TYPE = {
    TextField,
    ReactCodeInput,
  };
  const Component = COMPONENT_TYPE[renderComponent] || renderComponent;
  // 이부분에서 많이 헤맸다. Component Dynamic Naming 하는 법

  return (
    <Container>
      <InputLabel htmlFor={name} className="input-label">
        {inputLabel}
      </InputLabel>
      <Controller
        control={control}
        name={name}
        rules={rules}
        defaultValue={defaultValue}
        {...arg}
        render={({ field: { onChange, name, value } }) => {
          //console.log(value);
          return (
            <Component
              name={name}
              onChange={onChange}
              defaultValue={defaultValue && defaultValue}
              value={defaultValue || value}
              variant="outlined"
              {...componentProps}
            />
          );
        }}
      />
      <div className="error">
        <ErrorMessage errors={errors} name={name}>
          {({ messages }) =>
            messages &&
            Object.entries(messages).map(([type, message]) => (
              <p key={type}>{message}</p>
            ))
          }
        </ErrorMessage>
      </div>
    </Container>
  );
};
// label, input, error 메시지를 하나의 컴포넌트에서 관리할 수 있게 되었다. 

ControlledInput.propTypes = {
  renderComponent: PropTypes.string.isRequired,
  inputLabel: PropTypes.string,
  control: PropTypes.any,
  name: PropTypes.string,
  rules: PropTypes.object,
  errors: PropTypes.object,
  defaultValue: PropTypes.any,
  componentProps: PropTypes.object,
};

export default ControlledInput;
profile
더 나은 서비스를 고민하는 프론트엔드 개발자.

0개의 댓글