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 파일에 접근하여 코드를 확인할 것이다.
genderCode
가 number type
으로 전달되야 함을 확인할 수 있다. 비록 간단한 코드에선 확인이 간단하지만 복잡한 데이터구조를 갖는 오브젝트가 전달되고, 그 안에서 많은 로직이 수행된다면 개발효율은 떨어질 수 밖에 없다.
Component의 데이터 입출력에 더 나은 직관을 제공하기 위해 PropTypes
를 적용한 코드를 살펴보자.
치명적인 오류
ContactInfo
에 genderCode
를 살펴보자. 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;
컴포넌트의 입력값인 contact
는 shape
의 형태를 가지므로 shape
으로 지정한다. ( shape
과 objectOf
의 차이는 아래에 기술) 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
, objectOf
는 Custom 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를 필수로 명시하여 개발자에게 강제할 수 있다.