안녕하세요!
오늘은 state와 setState에 대해서 알아보겠습니다.
리액트의 강점 중 하나는 컴포넌트의 UI데이터가 변경될 때마다 자동으로 다시 render하는 것 입니다.
각 컴포넌트의 UI데이터가 state이고, 컴포넌트는 state가 변경되면 다시 render합니다.
그래서 항상 최신데이터를 웹을 방문하는 사용자에게 보여 줄 수 있습니다.
그러면 create-react-app을 이용해 프로젝트를 생성 후 컴포넌트를 만들어보겠습니다.
클릭 시 상태값이 증가하고 화면에 상태값이 출력됩니다.
// MyComponent.js
import React from 'react'
export default class MyComponent extends React.Component {
state = {
count : 0
}
handleOnClick = () => {
const {count} = this.state
this.setState({count:count+1})
}
render () {
const {count} = this.state
return (
<div>
<h3>{`COUNT : ${count}`}</h3>
<div style={{width:'100px', height:'100px', backgroundColor:'black'}} onClick={this.handleOnClick}>
<h3 style={{color:'white'}}></h3>
</div>
</div>
)
}
}
App.js에 컴포넌트를 추가합니다.
상태값으로 count가 있고 검은색박스를 클릭할 때마다 상태값이 +1씩 변경됩니다. 상태값이 변경되면 컴포넌트를 다시 그립니다.
클릭 시마다 COUNT가 1씩 증가합니다.
handleOnClick메서드를 수정해보겠습니다.
잘못된 예입니다.
handleOnClick = () => {
const {count} = this.state
this.setState({count:count+1})
this.setState({count:count+1})
}
이렇게 작성해도 count는 1씩만 증가합니다.
setState메서드가 비동기로 동작하기 때문입니다.
리액트는 여러개의 setState메서드를 Batch로, 즉, 일괄적으로 처리합니다.
만약 setState메서드가 동기적으로 처리된다면 하나의 setState를 만날 때마다 다시 그리기 때문에 성능이슈가 발생할 수 있습니다.
setState메서드의 인수에 함수를 입력할 수 있습니다.
handleOnClick을 수정하겠습니다.
handleOnClick = () => {
this.setState(prevState => ({count : prevState.count + 1}))
this.setState(prevState => ({count : prevState.count + 1}))
}
이제 클릭하면 2씩 증가됩니다.
setState에 입력된 함수는 자신이 호출되기 직전의 상태값을 인수로 받습니다. 따라서 첫 번째 setState가 변경한 상태값이 두 번째 setState의 인수로 들어갔습니다. setState는 비동기적으로 처리되지만 순서가 보장됩니다.
또 다른 잘못된 예입니다.
결론부터 밝히면 setState에서 객체형으로 인수를 넣어, state,props를 두 개 이상 사용할 경우 함수형으로 사용해야 한다는 것입니다.
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});
this.props와 this.state가 비동기적으로 업데이트될 수 있기 때문에 이런 코드도 지양해야 합니다.
이 코드 또한 함수형으로 바꿀 수 있습니다.
// Correct
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
setState에서 함수에 전달되는 두 번째 인수는 업데이트가 적용된 시점의 props가 옵니다.
setState에서 콜백을 사용할 수 있습니다.
handleOnClick을 수정하겠습니다.
handleOnClick = () => {
this.setState(prevState => ({count : prevState.count + 1}),()=>{
console.log(`state가 변경됨 : ${this.state.count}`)
})
}
state가 변경된 후에 로그가 출력됩니다.
이상으로 간단하게 클래스형 컴포넌트의 state와 setState에 대해 알아봤습니다.
함수형 컴포넌트에서 사용하는 Hook등에 관련해서는 나중에 따로 포스팅해볼게요
읽어주셔서 감사합니다