본문 바로가기
Web Programming/React

React - propTypes 예제로 이해하기( Custom validator )

by 맑은안개 2021. 8. 16.

PropTypes

React는 Component간 Props을 전달할 때 Type을 명시해줄 수 있다. Type을 명시함으로써 Component의 데이터 Type을 유추할 수 있어 소스가 더욱 명료해진다. 오류Type은 콘솔로그를 통해 확인할 수 있다.

연락처를 출력하는 간단한 앱을 만들어보자. 다음처럼 ContactInfo 컴포넌트에 contact 프로퍼티값을 전달한다.

📃App.js

import "./App.css";
import ContactInfo from "./components/ContactInfo";

function App() {
  return (
    <>
      <h1>Hello</h1>
      <ContactInfo
        contact={{
          name: "Hong gil dong",
          genderCode: 1,
                    address: "의정부시 의정부동",
          phone: "010-2342-1233",
        }}
      />
    </>
  );
}

export default App;

📃ContactInfo.js

import PropTypes from "prop-types";

function ContactInfo(props) {
  const gender = props.contact.genderCode === 1 ? "남" : "여";
  const contactStyle = {
    backgroundColor: "#60966f",
    margin: "5px",
    padding: "2px",
  };

  return (
    <div style={contactStyle}>
      <h3>
        {props.contact.name} ( {gender} )
      </h3>
      <span></span>
      {props.contact.phone}
      <br />
      {props.contact.address}
      <br />
    </div>
  );
}

export default ContactInfo;

위 코드에서 개발자는 ContactInfo에 값을 전달할 때 어떻게 접근할 것인가 ? 물론 ContactInfo.js 파일에 접근하여 코드를 확인할 것이다.

genderCodenumber type으로 전달되야 함을 확인할 수 있다. 비록 간단한 코드에선 확인이 간단하지만 복잡한 데이터구조를 갖는 오브젝트가 전달되고, 그 안에서 많은 로직이 수행된다면 개발효율은 떨어질 수 밖에 없다.

Component의 데이터 입출력에 더 나은 직관을 제공하기 위해 PropTypes를 적용한 코드를 살펴보자.

치명적인 오류

ContactInfogenderCode를 살펴보자. number 1이면 "남"을, 아니면 "여" 출력한다. 문자열로 genderCode를 넘기면 치명적 오류가 발생한다.

📃ContactInfo.js

<ContactInfo
  contact={{
    name: "Hong gil dong",
    genderCode: "1",
    address: "의정부시 의정부동",
    phone: "010-2342-1233",
  }}
/>

📃ContactInfo.js ( PropTypes 적용 )

      <br />
    </div>
  );
}

ContactInfo.propTypes = {
  contact: PropTypes.shape({
    name: PropTypes.string.isRequired,
    genderCode: PropTypes.number.isRequired,
    phone: PropTypes.string,
    address: PropTypes.string,
  }),
};

export default ContactInfo;

컴포넌트의 입력값인 contactshape의 형태를 가지므로 shape으로 지정한다. ( shapeobjectOf의 차이는 아래에 기술) Type의 종류는 여기를 참조한다.

반영 후 개발자도구에서 콘솔을 확인해보자.

shape vs objectOf

위에서 살펴본 shape은 objectOf와 무슨 차이가 있을까? objectOf는 구성하는 필드의 Type이 모두 같을 때 사용한다. 반면에 shape은 다른 Type을 갖는 필드로 구성된 object를 명시할 때 사용된다.

다음 코드는 스택오버플로우의 답변으로 예시를 발췌했다.

const objectOfProp = {
    latitude: 37.331706,
    longitude: -122.030783
}
// PropTypes.objectOf(PropTypes.number)

const shapeProp = {
    name: 'Jane',
    age: 25
}
// PropTypes.shape({ name: PropTypes.string, age: PropTypes.number })

Custom validator

arrayOf, objectOfCustom validator를 구성할 수 있다. 위의 예시에서 핸드폰번호 입력값을 정규식으로 유효성을 검증하는 Validator를 만들어보자.

우선, objectOf의 function값에 들어오는 프로퍼티값을 확인해보자.

ContactInfo.propTypes = {
  contact: PropTypes.shape({
    name: PropTypes.string.isRequired,
    genderCode: PropTypes.number.isRequired,
    phone: PropTypes.string,
    address: PropTypes.string,
  }),
};

ContactInfo.propTypes = {
  contact: PropTypes.objectOf(function (
    props,
    propName,
    componentName,
    location,
    fullName
  ) {
    console.log(props, propName, componentName, location, fullName);
  }),
};

export default ContactInfo;

object, array가 가진 객체 수 만큼 호출된다.

다음은 핸드폰번호 유효성 검증 Validator이다.

ContactInfo.propTypes = {
  contact: PropTypes.objectOf(function (
    props,
    propName,
    componentName,
    location,
    fullName
  ) {
    if (propName && propName === "phone") {
      if (
        /^01([0|1|6|7|8|9]?)-?([0-9]{3,4})-?([0-9]{4})$/.test(
          props[propName]
        ) === false
      ) {
        return new Error(
          "Invalid prop `" +
            propName +
            "` supplied to" +
            " `" +
            componentName +
            "`. Validation failed."
        );
      }
    }
  }),
};

정리하며..

간단한 예를 통해 propTypes 기능을 살펴보았다. 간단한 예제이지만 실무에서 충분히 발생할 수 있는 Types오류를 살펴보았다. eslint를 사용하면 propTypes를 필수로 명시하여 개발자에게 강제할 수 있다.

반응형