❗클래스 컴포넌트 기준으로 작성했습니다.
리액트에서 state는 컴포넌트 내부에서 바뀔 수 있는 값을 의미합니다. props는 컴포넌트가 사용되는 과정에서 부모 컴포넌트가 설정하는 값이며, 컴포넌트 자신은 해당 props를 읽기 전용으로만 사용할 수 있습니다.
import React, { Component } from "react";
export default class Counter extends Component {
constructor(props) {
super(props);
// state의 초깃값 설정하기
this.state = {
number: 0,
};
}
render() {
const { number } = this.state; //state를 조회할 때는 this.state로 조회합니다.
return (
<div>
<h1>{number}</h1>
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있습니다.
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
위 코드에서 각 코드가 어떤 역할을 하는지 알아보겠습니다.
컴포넌트에 state를 설정할 때는 다음과 같이 constructor 메서드를 작성하여 설정합니다.
constructor(props) {
super(props);
// state의 초깃값 설정하기
this.state = {
number: 0,
};
}
이는 컴포넌트의 생성자 메서드입니다.
constructor를 작성할 대는 반드시 super(props)를 호출해 주어야 합니다. 이 함수가 호출되면 현재 클래스형 컴포넌트가 상속받고 있는 리액트의 Component 클래스가 지닌 생성자가 함수를 호출해 줍니다.
그 다음에는 this.state값에 초기값을 설정해 주었습니다. 컴포넌트의 state는 객체 형식이어야 합니다.
render 함수를 알아봅시다.
render() {
const { number } = this.state; //state를 조회할 때는 this.state로 조회합니다.
return (
<div>
<h1>{number}</h1>
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있습니다.
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
render 함수에서 현재 state를 조회할 때는 this.state를 조회하면 됩니다.
그리고 button안에 onClick이라는 값을 props로 넣어 주었는데, 이는 버튼이 클릭될 때 호출 시킬 함수를 설정할 수 있게 해줍니다. 이를 이벤트를 설정한다고 합니다.
함수 내부에서는 this.setState라는 함수를 사용했는데 이 함수가 state 값을 바꿀 수 있게 해줍니다.
코드를 실행해 보겠습니다.

버튼을 클릭하면 setState에서 state값을 바꿔 줍니다.
constructor 메서드를 선언하지 않고 state의 초기값을 지정해 줄 수 있습니다.
import React, { Component } from "react";
export default 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을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있습니다.
this.setState({ number: number + 1 });
}}
>
+1
</button>
</div>
);
}
}
this.setState를 사용하여 state 값을 업데이트할 때는 상태가 비동기적으로 업데이트 됩니다. 만약 다음과 같이 onClick에 설정한 함수 내부에서 this.setState를 두 번 호출하면 어떻게 될까요?
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있습니다.
this.setState({ number: number + 1 });
this.setState({ number: number + 1 });
}}
this.setState를 두 번 사용했는데도 불구하고 버튼을 클릭할 때 숫자가 1씩 더해집니다. this.setState를 사용한다고 해서 state 값이 바로 바뀌지는 않기 때문입니다.
이에 대한 해결책은 this.setState를 사용할 때 객체 대신에 함수를 인자로 넣어주는 것입니다.
this.setState의 인자로 함수를 넣어줄 때는 코드를 다음과 같은 형식으로 작성합니다.
this.setState((prevState, props) => {
return {
// 업데이트하고 싶은 내용
}
})
여기서 prevState는 기존 상태이고, props는 현재 지니고 있는 props를 가리킵니다. 만약 업데이트 과정에서 props가 필요하지 않다면 생략해도 됩니다.
<button
// onClick을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있습니다.
this.setState((prevState) => {
return {
number: prevState.number + 1,
};
});
// 위 코드와 아래 코드는 완전히 똑같은 기능을 합니다.
// 아래 코드는 함수에서 바로 객체를 반환한다는 의미입니다.
this.setState((prevState) => {
return {
number: prevState.number + 1,
};
});
}}
>
+1
</button>
위 코드처럼 작성하면 클릭했을 때 +2씩 올라갑니다.
setState를 사용하여 값을 업데이트하고 난 다음에 특정 작업을 하고 싶을 때는 setState의 두 번째 파라미터로 콜백(callback) 함수를 등록하여 작업을 처리할 수 있습니다.
import React, { Component } from "react";
export default 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을 통해 버튼이 클릭되었을 때 호출할 함수를 지정합니다.
onClick={() => {
// this.setState를 사용하여 state에 새로운 값을 넣을 수 있습니다.
this.setState({ number: number + 1 }, () => {
console.log("방금 setState가 호출되었습니다.");
console.log(this.state);
});
}}
>
+1
</button>
</div>
);
}
}

number를 +1 해주고 그다음 콘솔을 찍어주었습니다.