컴포넌트의 기본 속성
리액트는 속성의 기본값을 설정할 수 있는 기능으로 defaultProps를 정적 클래스 속성으로 추가할 수 있다. defaultProps를 설정하면 컴포넌트 속성이 누락되었을 때 기본값을 렌더링할 수 있는 이점이 있다. 예를 들어 사용자 정의가 가능한 라벨을 렌더링하는 컴포넌트를 만들 때 사용자 정의 값이 누락된 경우 기본값을 보여줄 수 있다. 또 기본값을 설정하여 같은 값을 반복해서 다시 설정하는 것을 피할 수 있다.
class DatePicker extends React.Component {
...
}
DatePicker.defaultProps = {
currentDate: Date(),
rows: 4,
}
class Button extends React.Component {
render(){
return <button>{this.props.buttonLabel}</button>
}
}
Button.defaultProps = {buttonLabel: 'Submit'} //정적 클래스 속성 부여
//buttonLabel 속성이 누락되면 'Submit' 이라는 속성이 설정된다.
React 속성 타입과 유효성 검사
React 컴포넌트 클래스에 propTypes 정적 속성을 이용하면 속성 타입을 설정할 수 있다. 속성 타입 기능은 자료형을 강제하는 대신 경고를 보여준다. development mode에서는 속성 타입이 일치하지 않으면 콘솔에서 경고 메시지를 확인할 수 있다. (production mode에서는 경고 문구 나타나지 않음)
class Datepicker extends React {
...
}
Datepicker.propTypes = {
currentDate: PropTypes.string,
rows: PropTypes.number,
locale: PropTypes.oneOf(['US', 'CA'])
] //프론트엔드의 사용자 입력 유효성 검사를 propTypes에 의존하는 것은 좋지 않음.
React 15.5 이후 버전에서는 prop-types라는 별도 패키지로 제공되기 때문에 prop-types를 HTML에 패키지 추가해야 한다. 패키지는 전역객체 window.PropTypes가 된다. (확인해 보기)
isRequired를 타입에 추가하면 필수 속성으로 지정할 수 있다.
propTypes를 사용하여 타입 유효성 검사를 할 수도 있다. 사용자 정의 유효성 검사를 구현하기 위해 Error 인스턴스를 반환하는 표현식을 생성한다.
Button.propTypes = {
handler: PropTypes.func.isRequired, //함수를 값으로 하는 handler 필수
title: PropTypes.string //title속성은 문자열 값을 선택 적용 가능
email(props, propName, componentName) {
let emailRegularExpression = ... //email 유효성 검사를 위한 정규표현식 사용하는 방법 나열
if(!emailRegularExpression.test(props[propName])){
return new Error('Email Validation Fail')
}
}
}
자식 엘리먼트 렌더링
children 속성은 모든 자식을 {this.props.children} 으로 렌더링할 수 있다. 단순 렌더링 이외에도 <div>를 추가해서 자식 엘리먼트와 함께 렌더링할 수 있다.
class Content extends React {
render()[
return(
<div>{this.props.children}</div>
)
}
]
ReactDOM.render(
<div>
<Content> //부모 컴포넌트 Content는 <h1>과 <p>를 자식으로 갖는다.
<h1>React</h1>
<p>Rocks</p>
</Content>
</div>
document.getElementById('content')
}
children 속성은 자식 엘리먼트가 하나 이상 있는 경우 배열이 되어 {this.props.children[0]} 처럼 개별 엘리먼트에 접근이 가능하다. (하나뿐이면 배열이 아니다) 이때 React.Children.count(this. props.children)을 사용하면 자식 엘리먼트의 수를 정확하게 확인할 수 있다. count외에도 map(), toArray()같은 다른 메서드도 있다.
코드 재사용을 위한 React 고차 컴포넌트 (Higher Order Component, HOC) 생성하기 (리액트 이해 - Higher Order Component로 컴포넌트 재사용하기)
고차 컴포넌트를 이용하면 컴포넌트에 추가적인 로직을 적용해서 컴포넌트를 향상시킬 수 있다. (고차 컴포넌트를 통해 다른 컴포넌트가 기능을 상속받는 패턴 → 고차 컴포넌트를 통해 코드 재사용이 가능하다.)
HOC는 리액트 컴포넌트를 인자로 받아서 새로운 리액트 컴포넌트를 리턴하는 함수이다. EnhancedReactComponent는 ReactComponent 의 Props를 변경한다거나, 리액트 컴포넌트에 새로운 props를 추가하여 전달하거나 아예 새로운 컴포넌트를 return할 수 있다.
const HOC = ReactComponent => EnhancedReactComponent;
리액트에서 컴포넌트를 만들때 가장 많이 사용되는 패턴은 컴포지션 패턴이다.
HOC를 만드는 방법에는 Class기반 컴포넌트를 리턴하는 방법과 Function 기반 컴포넌트를 리턴하는 방법이 있다.
const withHOC = WrappedComponent => {
const newProps = {
loading: false,
};
return props => {
return <WrappedComponent {...props} {...newProps} />
}
}; //Functional Component 리턴
const withHOC = WrappedComponent => {
const newProps = {
loading: false,
};
return class extends React.Component {
render() {
return <WrappedComponent {...this.props} {...newProps} />
}
}
}; //Class Component 리턴
export default withHOC(AnyComponent); //HOC 사용할 때
const withLoading = (WrappedComponent) => (props) =>
props.isLoading
? <div>Loading ...</div>
: <WrappedComponent { ...props } />
//isLoading prop을 받아서 true일땐 로딩 컴포넌트를 렌더링하고,
//false일 땐 원하는 컴포넌트를 렌더링하는 HOC
export default withLoading(TodoList);
//TodoList라는 컴포넌트를 withLoading HOC로 래핑해서 로딩중일때는
//로딩 화면을 보여주도록 처리한다.
프레젠테이션 컴포넌트와 컨테이너 컴포넌트