Props
properties를 줄인 표현으로 컴포넌트 속성을 설정할때 사용한다. 해당 컴포넌트를 불러와 사용하는 부모 컴포넌트에서 설정한다.
props 기본값 설정 방법
defaultProps를 사용한다.
const MyComponent = props => {
return <div>안녕하세요, {props.name}입니다.</div>
}
MyComponent.defaultProps = {
name: '설정하지 않은 이름'
}
<MyComponent/>
propTypes를 통한 props검증
필수 props를 지정하거나 props의 타입을 지정할떄는 propTypes를 사용한다. defaultProps를 설정하는 방법과 유사하다.
prop에 유효하지 않은 값이 전달 되었을 때, 경고문이 JavaScript 콘솔을 통해 보인다. propTypes는 성능상의 이유로 개발 모드(Development mode) 에서만 확인된다.
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
태그 사이의 내용을 보여주는 children
컴포넌트 태그 사이의 작성한 문자열을 컴포넌트 내부에서 사용하고 싶을 경우 children을 사용한다.
const MyComponent = props => {
return <div>안녕하세요, {props.name} {props.children}</div>
}
<MyComponent name='김은수'>입니다.</MyComponent>
클래스형 컴포넌트에서 props 사용하기
this.props로 참조한다. defaultProps, propsTypes 모두 동일한 방법으로 사용 가능하다.
읽기 전용
함수 컴포넌트나 클래스 컴포넌트 모두 props를 수정해선 안된다. React는 유연하지만 한가지 엄격한 규칙이 있으며 모든 React Component는 자신의 props를 다룰 때 반드시 순수 함수처럼
동작해야 한다.
//순수함수, 입력값을 바꾸혀 하지 않는다. 입력값이 동일하다면 동일한 결과를 반환한다.
function sum(a, b) {
return a + b;
}
//순수함수가 아니다. 입력값을 변경한다.
function withdraw(account, amount) {
account.total -= amount;
}
State
State는 props와 유사하지만, 비공개이며 컴포넌트에 의해 완전히 제어된다.
- 클래스형 컴포넌트가 지니고 있는 state
- 함수형 컴포넌트에서
useState()
라는 함수를 통해 사용하는 state
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {date: new Date()};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock/>,
document.getElementById('root')
);
<Clock />
컴포넌트가ReactDOM.render()
로 전달되었을 때React
는Clock
컴포넌트의constructor
를 호출constructor
생성자 내부에서Clock
이 현재 시각이 포함된 객체로this.state
를 초기화- React는 Clock 컴포넌트의 render() 메서드를 호출
- React는 화면에 표시되어야 할 내용을 알게 됨
- React는 Clock의 렌더링 출력값을 일치시키기 위해 DOM을 업데이트
- Clock 출력값이 DOM에 삽입되면, React는 componentDidMount() 생명주기 메서드를 호출
- componentDidMount() 내부에서 Clock 컴포넌트는 매초 컴포넌트의 tick() 메서드를 호출하기 위한 타이머를 설정하도록 브라우저에 요청
- 매초 브라우저가 tick() 메서드를 호출
- tick() 내부에서는 setState()에 현재 시각을 포함하는 객체를 호출하면서 UI 업데이트를 진행
- setState() 호출 덕분에 React는 state가 변경된 것을 인지하고 화면에 표시될 내용을 알아내기 위해 render() 메서드를 다시 호출
- 이 때 render() 메서드 안의 this.state.date가 달라지고 렌더링 출력값은 업데이트된 시각을 표현
- React는 이에 따라 DOM을 업데이트합니다.
- Clock 컴포넌트가 DOM으로부터 한 번이라도 삭제된 적이 있다면 React는 타이머를 멈추기 위해 componentWillUnmount() 생명주기 메서드를 호출.
state 올바르게 사용하기
직접 state를 수정하지 않는다.
this.state를 지정 할 수 있는 유일한 공간은 constructor 하나다.
// 이 코드는 컴포넌트를 리렌더링하지 않는다.
this.state.comment = 'Hello';
setState()를 사용한다.
this.setState({comment: 'Hello'});
state 업데이트는 비동기적일 수 있다.
React는 성능을 위해 컴포넌트에 작성된 setState() 함수들을 단일 업데이트로 한번에 처리할 수 있다.
this.props, this.state가 비동기적으로 업데이트 될 수 있기 때문에 다음 state을 이용하는 작업에서 해당 값에 의존해서는 안된다.
아래와 같은 코드는 실패할 수 있다.
this.setState({
counter: this.state.counter + this.props.increment,
});
객체보다는 함수를 인자로 사용하는 다른 형태의 setState() 함수를 사용하여 해결할 수 있다. 첫번째 파라미터는 이전 state, 두번쨰 파라미터는 업데이트가 적용된 시점의 props를 받는다.
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
state 업데이트는 병합된다.
별도의 setState() 호출을 사용해 독립적으로 업데이트할 수 있습니다. 이후에 state는 병합되어 업데이트 된다.
class App extends Component {
constructor(props) {
super(props);
this.state = {
posts: [],
comments: []
};
}
componentDidMount() {
fetchPosts().then(response => {
this.setState({
posts: response.posts
});
});
fetchComments().then(response => {
this.setState({
comments: response.comments
});
});
}
render({
<.../>
}
)
;
}
Top-down
“하향식(top-down)” 또는 “단방향식” 데이터 흐름이라고 한다. 모든 state는 항상 특정한 컴포넌트가 소유하고 있으며 그 state로부터 파생된 UI 또는 데이터는 오직 트리구조에서 자신의 **
“아래”에 있는 컴포넌트에만 영향을 미친다.**
'독서 > React' 카테고리의 다른 글
[React]Component란? (0) | 2021.03.22 |
---|---|
[React] Element란? (0) | 2021.03.22 |
[React] JSX란? (0) | 2021.03.22 |