상위 컴포넌트가 하위 컴포넌트에게 내려주는 데이터
하위컴포넌트는 props를,
const App = () => (
<div>
<h2>To Do List !</h2>
<TodoList todos={["eat pizza", "eat rice"]} />
</div>
);
const TodoList = props => (
<ul>
<li>{props.todos[0]}</li>
<li>{props.todos[1]}</li>
</ul>
);
컴포넌트가 갖는 상태,
객체의 형태로 컴포넌트 내에서 보관하고 관리한다.
class GroceryList extends React.Component {
constructor(props) {
super(props);
this.state = { // state 정의
isBold: false
};
}
onListItemClick = () => {
this.setState({ // state 변경
isBold: !this.state.isBold
});
};
render() {
const style = {
fontWeight: this.state.isBold ? "normal" : "bold"
};
return (
<ul>
<li style={style} onClick={this.onListItemClick}>
{this.props.todo[0]}
</li>
<li>{this.props.todo[1]}</li>
</ul>
);
}
}
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
컴포넌트가 브라우저에 보여질 때, 업데이트될 때, 사라질 때 각 단계 전, 후로 특정 메서드가 호출된다
react 공식 문서에 예시가 잘나와 있어서 가져왔다
class Clock extends React.Component {
constructor(props) { // 1. Clock 컴포넌트의 생성자 호출
super(props);
this.state = {date: new Date()}; // 2. 현재 시각이 포험된 객체로 초기화
}
componentDidMount() { // 5. componentDidMount() 메서드 호출
this.timerID = setInterval( // 6. 1초에 한번씩 tick 메서드 호출
() => this.tick(),
1000
);
}
componentWillUnmount() {
/* Clock 컴포넌트가 DOM으로부터 한번이라도 삭제된 적이 있다면
React는 타이머를 멈추기 위해 componentWillUnmount 메서드를 호출한다. */
clearInterval(this.timerID);
}
tick() {
this.setState({ // 7. state가 변경되면 render 메서드를 다시 호출한다.
date: new Date()
});
}
render() { // 3. render 메서드 호출
return ( // // 4. 화면 렌더링
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
constructor()
=> 생성자 호출import React from 'react';
import ReactDOM from 'react-dom';
const HelloWorld = () => (
<div>HELLO WORLD</div>
);
ReactDOM.render(<HelloWorld />, document.getElementById("root"));
해당 특징은 신기해서 따로 빼서 글을 정리한다. => 예제
예제에서,
1. Follow버튼을 누르고
2. 3초가 지나기 전에 체크박스 옵션을 바꾼다
3. 알림창의 글을 읽어본다
결과,
이 예제에서는 함수형 컴포넌트가 보여주는 패턴이 올바른 케이스이다. 내가 어떤 사람을 팔로우하고 다른 사람의 프로필로 이동했다 하더라도 컴포넌트가 이를 헨갈려서는 안된다.
클래스형 컴포넌트에서 버튼을 누른 후 옵션값을 바꿀경우에 알림창에 바뀐 옵션값을 노출하는 이유는?
class ProfilePage extends React.Component {
showMessage = () => {
alert('Followed ' + this.props.user);
};
showMessage
메서드는 this.props.user
로부터 값을 불러온다. props는 리액트에서 불변값이지만 this
는 변경이 가능하고 조작할 수 있다.
리액트가 시간이 지남에 따라 this
를 변경하기 때문에 render
나 라이프사이클 메서드를 호출할 때 업데이트된 값들을 읽어올 수 있는 것이다.
따라서 요청이 진행되고 있는 상황에서 클래스 컴포넌트가 다시 렌더링 된다면 this.props
또한 바뀐다. 그래서 showMessage
메서드가 새로운 props
의 user
를 읽는 것이다
해결방법
자바스크립트의 클로저로 해결할 수 있다.
props
의 값을 render될때의 값으로 고정
class ProfilePage extends React.Component {
render() {
// props의 값을 고정!
const props = this.props;
// Note: 여긴 *render 안에* 존재하는 곳이다!
// 클래스의 메서드가 아닌 render의 메서드
const showMessage = () => {
alert('Followed ' + props.user);
};
const handleClick = () => {
setTimeout(showMessage, 3000);
};
return <button onClick={handleClick}>Follow</button>;
}
}
렌더링된 값을 고정시키고 싶을때는 함수형 컴포넌트를 사용하자.
import React from "react";
import ReactDOM from "react-dom";
class TodoListItem extends React.Component {
constructor(props) {
super(props);
this.state = {
done: false
};
}
onListItemClick() {
this.setState({
done: !this.state.done
});
}
render() {
const style = {
textDecoration: this.state.done ? "line-through" : "none"
};
return (
<li style={style} onClick={this.onListItemClick.bind(this)}>
{this.props.todo}
</li>
);
}
}
ReactDOM.render(
<TodoListItem todo={["one", "two"]} />,
document.getElementById("root")
);