state
state란 컴포넌트 내부에서 바뀔 수 있는 값을 의미한다.
props는 부모컴포넌트에서 설정하여 자신의 컴포넌트에서 읽기 전용으로만 사용할 수 있다. 자신의 컴포넌트에서 동적인 데이터를 관리하려면 state를 사용해야한다.
state의 종류로 두가지가 있다. 클래스형 컴포넌트가 지니는 state와 함수형 컴포넌트의 useState함수에서 사용하는 state가 있다.
클래스형 컴포넌트 state
1 클래스형 컴포넌트에서 state는 생성자(constructor) 매서드 내에서 초기화 되고 this.state를 객체 형태로 설정한다.
import React, { Component } from "react";
class Counter extends Component{
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return <div>Count: {this.state.count}</div>;
}
}
2 state는 직접 변경할 수 없고 반드시 setState메서드를 사용하여 상태를 업데이트해야 한다.
import React, { Component } from "react";
class Counter extends Component{
constructor(props) {
super(props);
this.state = {
count: 0
};
}
increment = () =>{
this.setState({ count: this.state.count+1});
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>+1</button>
</div>
);
}
}
3 리액트에서 setState는 비동기적으로 처리된다. 즉 상태 업데이트 요청이 즉시 처리되지 않고 리액트가 내부적으로 관리하는 작업 스케줄에 따라 나중에 처리될 수 있다.
import React, { Component } from "react";
class Counter extends Component{
constructor(props) {
super(props);
this.state = {
count: 0
};
}
increment = () =>{
this.setState({ count: this.state.count+1});
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() =>{
this.increment();
this.increment();
}}>+1</button>
</div>
);
}
}
setState는 비동기적으로 작동하기 때문에 button에서 +1을 클릭했을 때 this.increment를 두 번 호출했지만 상태값이 두 번 업데이트 되지 않는다.
이를 해결하기 위해 setState의 콜백함수 형태를 사용하면 이전 상태(prevstate)를 안전하게 참조하여 원하는 동작을 구현할 수 있다.
import React, { Component } from "react";
class Counter extends Component{
constructor(props) {
super(props);
this.state = {
count: 0
};
}
increment = () =>{
this.setState((prevState)=>({
count: prevState.count+1
}));
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() =>{
this.increment();
this.increment();
}}>+1</button>
</div>
);
}
}
4 state객체안에 여러개의 값을 지정할 수 있다.
import React, { Component } from "react";
class Counter extends Component{
constructor(props) {
super(props);
this.state = {
value: 0,
value2: 0,
value3: 0
...
};
}
render() {
...
}
}
5 constructor를 사용하지 않고 state객체안의 값을 지정해 주는 방법이 있다.
import React, { Component } from "react";
class Counter extends Component{
state = {
value: 0,
value2: 0,
value3: 0
}
render() {
const {value, value2, value3} = this.state;
return ...;
}
}
함수형 컴포넌트 state
1 함수형 컴포넌트에서 state를 관리하려면 useState 훅을 사용한다.
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+1</button>
</div>
);
}
useState는 배열 형태로 [state 변수, state를 변경하는 함수]를 반환한다.
useState의 인자는 state의 초기값이다.
2 useState는 하나의 상태만 관리하는 것이 아니라 여러 상태를 관리할 수 있다.
import React, { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
const [count2, setCount2] = useState(25);
return (
...
);
}
3 state를 업데이트 시에 이전상태 값을 기반으로 새 값을 계산하려면 함수형 업데이트를 사용한다.
function Counter() {
const [count, setCount] = useState(0);
const increment = () => setCount((prevCount) => prevCount + 1);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+1</button>
</div>
);
}
4 state의 값을 객체로 사용할 수 있다.
function Counter() {
const [count, setCount] = useState({value: 0, value2: 0 ... });
return (
...
);
}