출처 - 리액트를 다루는 기술(김민준 지음)
state와 props 비교
state와 props 모두 컴포넌트에서 사용하거나 렌더링할 데이터를 담고 있지만 역할은 다르다.
state : 컴포넌트 내부에서 바뀔 수 있는 값 (컴포넌트 내부에서 값을 업데이트 가능)
props : 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값
(컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있다)
리액트에는 2가지 종류의 state가 있다
1. 클래스형 컴포넌트의 state
2. 함수형 컴포넌트에서 useState 함수를 통해 사용하는 state
(1) 클래스형 컴포넌트의 state
Counter.js 파일을 생성한다
constructor 메서드를 사용하여 state를 생성할 수도 있지만 굳이 그러지 않아도 된다
setState 메서드로 state 값을 업데이트한다
// Counter.js
import React, { Component } from 'react';
class Counter extends Component {
state = {
number: 0,
fixedNumber: 0,
};
render() {
const { number, fixedNumber } = this.state; // state를 조회할 때는 this.state로 조회
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값: {fixedNumber}</h2>
<button
onClick={() => {
/* setState는 state 값을 바꿀 수 있게 해준다 */
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
this.setState에 객체 대신 함수 인자 전달하기
this.setState를 사용하여 state 값을 업데이트할 때는 상태가 비동기적으로 업데이트 된다
this.setState의 인자로 함수를 넣으면 this.setState를 2번 이상 호출할 수 있다
// Counter.js
import React, { Component } from 'react';
class Counter extends Component {
state = {
number: 0,
fixedNumber: 0,
};
render() {
const { number, fixedNumber } = this.state;
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값: {fixedNumber}</h2>
<button
onClick={() => {
this.setState((prevState) => {
return {
number: prevState.number + 1,
};
});
// 위 코드와 아래 코드는 똑같은 기능을 한다
// 아래 코드는 함수에서 바로 객체를 반환한다는 의미이다
this.setState((prevState) => ({
number: prevState.number + 1,
}));
}}
>
+1
</button>
</div>
);
}
}
export default Counter;
+1 버튼을 눌렀을 때 숫자가 2씩 증가하게 된다
this.setState가 끝난 후 특정 작업 실행하기
setState의 2번째 매개변수로 콜백함수를 등록하면 이후 작업을 추가할 수 있다
// Counter.js
import React, { Component } from 'react';
class Counter extends Component {
state = {
number: 0,
fixedNumber: 0,
};
render() {
const { number, fixedNumber } = this.state;
return (
<div>
<h1>{number}</h1>
<h2>바뀌지 않는 값: {fixedNumber}</h2>
<button
onClick={() => {
this.setState(
{
number: number + 1,
},
() => {
console.log('방금 setState가 호출되었습니다.');
console.log(this.state);
}
);
}}
>
+1
</button>
</div>
);
}
}
export default Counter;