IT_susu

react 컴포넌트에서 데이터 다루기(2) state 본문

[ javascript ]/react

react 컴포넌트에서 데이터 다루기(2) state

고베베 2018. 6. 25. 14:46

props는 부모 자식 관계에서 데이터를 주고 받는 것이지만, state는 하나의 컴포넌트 내부에서 데이터 값이 변하는 것입니다.

state의 값을 변경할 때는 항상 setstate라는 함수를 사용하여 변경합니다. 왜냐하면 setstate함수가 호출되면 컴포넌트가 리렌더링되도록 설계되어 있기 때문입니다.

setstate를 거치지 않고 값을 직접 변경해도 리렌더가 되지 않으면 소용없겠죠? 뷰에 업데이트가 되지 않을테니까요.

import React, { Component } from 'react';

export default class Counter extends Component{

state = {
	number: 0 -------------------------- 1
}

handleIncrease = () => {
  this.setState({ -------------------------- 3
  	number: this.state.number+1
  })
}

handleDecrease = () => {
  this.setState({
  	number: this.state.number-1
  })
}

render(){
  return(
    <div>
      <h1>Counter</h1>
      <div>값 : {this.state.number}</div>
      <button onClick={this.handleIncrease}>+</button> -------------------------- 2
      <button onClick={this.handleDecrease}>-</button>
    </div>
    )
  }
}

 

1. 컴포넌트 간의 교류가 아니라 하나의 컴포넌트 내부에서 값을 바꾸는 것이 state라고 했습니다. 따라서 다른 컴포넌트는 볼 필요 없이 이거 하나만 보면 됩니다.

state를 이용하여 데이터를 조작할 때에는 state라는 프로퍼티를 만들어서 그 안에 객체형식으로 값을 저장하여 사용합니다.

 

2. 유저의 행동에 의해서 값이 변경되겠죠? 즉, 이벤트가 발생해야 합니다. 따라서 해당 dom요소에 이벤트를 걸어놓습니다. 여기서는 onClick이 되겠네요.

그리고 value에다가 {}를 넣어 자바스크립트 문법임을 표시하고, class에 미리 정의해 놓은 메서드를 연결합니다. 메서드를 호출하진 않습니다. 여기서 호출을 하면 값이 계속 리로드됩니다.

 

3. 위에서도 설명했듯이 setState를 이용하여 값을 변경해 주셔야 합니다. 위의 방법은 this.state를 또 찾기 때문에 자원을 낭비하므로 비구조화 할당을 활용하여 아래와 같이 바꿀 수도 있습니다.

handleIncrease = () => {
	const { number } = this.state;
	this.setState({
		number : number + 1
	});
}

지금은 setState에서 객체형식으로 number값을 넘겼죠? 객체형식이 아닌 상태로 값을 넘기면 아래와 같은 에러가 뜹니다.

 

setState(...): takes an object of state variables to update or a function which returns an object of state variables.

[번역] setState (...) : 업데이트 할 상태 변수의 객체 또는 상태 변수의 객체를 반환하는 함수를 취합니다.

 

즉, setState는 객체 또는 객체를 반환하는 함수형식으로 작성해야 합니다. 

그럼 이번엔 객체를 반환하는 함수형식으로 위의 메서드를 바꿔봅시다.

handleIncrease = () => {
	this.setState(
		(state) => ({
 			number: state.number + 1
		})
	);
}

애로우 함수는 한 줄인 경우 그 줄을 그대로 리턴해주므로 현재 객체를 리턴하는 함수입니다.

 

비구조화 할당 문법으로 더 바꾸면, 아래와 같이 작성할 수도 있습니다.

handleIncrease = () => {
	this.setState(
		({ number }) => ({
			number: number + 1
		})
	);
}

 

특징1) state 업데이트는 비동기적일 수도 있습니다.

성능을 위해 react는 여러 setState를 합쳐서 한꺼번에 처리할 수도 있습니다.

이를 방지하고 싶다면 함수를 인자로 사용하는 setState를 사용합니다.

this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

 

특징2) state는 얕게 병합됩니다.

state는 객체로 되어 있지만, 첫번째 depth에서는 나머지들을 그대로 냅두고 적은 코드만 변경합니다. 하지만 얕은 복사처럼 얕게 되어있어서, 두번째 참조형 데이터가 나오면 대체해버립니다.

따라서 편리하게 사용하기 위해 immer같은 플러그인을 사용합니다.

Comments