본문 바로가기
Programming 개발은 구글로/Web[프론트엔드&백엔드]

[Web] React state & setState 개념 이해

by 40대직장인 2022. 6. 27.

React state & setState 개념 이해

: 동적인 데이터 처리할 때 state를 사용한다.

import React, { Component } from 'react';

class Counter extends Component {
  state = {
    number: 0
  }

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

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

  render() {
    return (
      <div>
        <div>카운터</div>
        <div>값: {this.state.number}</div>
        <button onClick={this.increase}>+</button>
        <button onClick={this.decrease}>-</button>
      </div>
    );
  }
}

export default Counter;

 

여기서 increase() 함수와 decrease() 함수를 아래와 같이 작성할 수도 있습니다.

  increase() {
    this.setState({
      number: this.state.number + 1
    });
  }

  decrease() {
    this.setState({
      number: this.state.number - 1
    });
  }

하지만, 이렇게 작성을 하면 버튼에 이벤트가 발생이 되었을 경우 this가 undefined 처리가 될 수도 있습니다.

 

첫 번째 코드에서처럼 화살표 함수 형태(ES6 문법)로 작성을 하든지 아니면 constructor로 처리를 하시면 됩니다.

 constructor(props) {
    super(props);
    this.increase = this.increase.bind(this);
    this.decrease = this.decrease.bind(this);
  }

 

1. class 사용 시기

: state와 Lifecycle을 사용할 때 class를 사용합니다. Hook이 없었던 시절에는 함수형 컴포넌트에서 state와 lifecycle 관리를 못 했지만, 지금은 함수형 컴포넌트에서 Hook()을 사용하여 useState, useEffect을 활용하여 state와 Lifecycle 관리가 가능합니다.

 

// class fields를 사용하지 않는 경우
class Checkbox extends React.Component { // 이전에는 constructor를 정의하고 super(props)를 호출
    constructor(props) {
        super(props);
        this.state = { hanPy: true };
    };
...
};

// class fields를 사용하는 경우
class Checkbox extends React.Component {
        state = { hanPy: true };
...
};

대부분 super와 constructor을 많이 사용한다. 하지만 클래스필드 문법을 사용하면 super(1)와 constructor를 사용하지 않아도 된다.

 

(1) super

: 자바스크립트에서는 super는 부모 클래스 생성자를 가리킨다. 리액트에서는 React.Component를 가리킨다.

 

핵심은 리액트에서는 super(props) 선언전까지 constructor에서 this 키워드를 사용할 수 없다. 그러나, 어떤 경우에는 super 키워드 안에 props를 작성하지 않아도 render 메서드에서 this.props를 사용할 수 있다.

리액트가 클래스 문법에 대한 지원이 추가 되었을때, 단지 ES6 클래스로써의 지원만을 한 것은 아니었다. 클래스의 넓은 범위의 추상화를 지원하는 것이 목표였다. 물론 리액트는 constructor가 실행된 후 this.props를 할당된다. 그러나 constructor에서 super()가 불려진 이후에도 this.props는 여전히 undefined 일 것이다. 디버깅을 위해 꼭 필요한 것은 하니지만 super(props)로 작성하는 것을 추천한다.

 

2. props와 state 비교

props: 부모 컴포넌트가 자식 컴포넌트에게 주는 값. 자식 컴포넌트는 props를 받아오기만 하고 직접 수정할 수는 없습니다.

state: 컴포넌트 내부에서 선언하면 내부에서 값 변경 가능합니다.

 

3. setStae

: 메소드에 this.setState라는 것이 있다. state에 있는 값을 바꾸기 위해서는 this.setState를 무조건 거쳐야 한다. 

 

리액트에서는, 이 함수가 호출되면 컴포넌트가 다시 렌더링이 되도록 설계되어있습니다.

state = {
    number : 0,
    name : 'Lim'
}

this.setState({ number:1 })을 하면, Lim은 그대로 있고, namber가 0에서 1로 바뀐다.

 

그러나 setState는 객체의 깊숙한 곳까지는 확인하지 못한다.

state = {
    number : 0,
    name : {
    	first: "chul"
        last: 'Lim'
    }
}

※ first와 last 값을 업데이트 할 수 없습니다.

 

state 안에 객체가 들어있을 떄는 객체 내부의 값을 바꾸려면, 객체 내부에서 불러오고 싶은 위치를 재지정해야 한다.

this.setState({
  number: 0,
  name: {
    ...this.state.name,
    last: "Lim"
  }
});

… 은 자바스크립트의 전개 연산자입니다. 기존의 객체 안에 있는 내용을 해당 위치에다가 풀어준다는 의미입니다. 그다음에 우리가 설정하고 싶은 값을 또 넣어주면 해당 값을 덮어쓰게 됩니다.

 

4. setState 코드 문법

기존 작성한 코드

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

 

this.state 조회 생략하는 문법 사용

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

 

setState에 updater 함수를 만들어서 전달하는 문법 사용

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

 

비구조화 할당 문법 사용

 - 비구조화 할당 문법은 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 JavaScript 표현식입니다.

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

 

5. React에서 이벤트 설정 시 주의사항 

<button onClick={this.increase}>+</button>
  • 이벤트 이름은 camel Case로 설정
  • 이벤트에 전달되는 값은 함수만 설정 

     - 만약에 this.increase()로 처리를 하면 Rendering을 할 때마다 해당 함수가 호출이 되어 계속 반복이 됩니다.

 


참고 글: 누구든지 하는 리액트 4편: props 와 state

https://velopert.com/3629

 

 

 

댓글