[React] Component - 상태 관리(state)

JhsK·2021년 2월 6일
0
post-thumbnail

프로퍼티의 특징은 컴포넌트 내부에서 값을 바꿀 수 없다라는 특징이 있다. 그렇지만 우리가 사용하는 일반적인 웹은 댓글을 남기는 등의 값을 바꿔야 하는 경우가 무수히 많다. 그러한 경우에 state를 사용한다.

state로 상태 관리하기

state는 '값을 저장하거나 변경할 수 있는 객체'로 보통 버튼을 클릭하거나 값을 입력하는 등의 이벤트와 함께 사용된다. 아래의 코드는 setTimeout() 함수를 통해 4초 후 state에 저장되어 있는 값을 변경하는 코드이다.

import React, { Component } from "react";

class StateExample extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      formData: "no data",
    };
    this.handleData = this.handleData.bind(this);
    setTimeout(this.handleData, 4000);
  }
  handleData() {
    const data = "new data";
    const { formData } = this.state;
    this.setState({
      loading: false,
      formData: data + formData,
    });

    console.log("loading값", this.state.loading);
  }
  render() {
    return (
      <div>
        <span>로딩중: {String(this.state.loading)}</span>
        <span>결과: {this.state.formData}</span>
      </div>
    );
  }
}

export default StateExample;

위의 코드를 보면 constructor(props)안에서 컴포넌트에서 관리하려는 변수 state 초기값을 this.state에 객체 형태로 정의하였고, handleData() 함수에서 컴포넌트 특수 변수 this.state를 사용하여 state 값에 접근하여 this.setState()를 사용하여 state 값을 변경한다.

이런식으로 state를 사용할 수 있는데 state를 사용할 때에는 몇가지 주의항이 있다.

  • 생성자(constructor)에서 반드시 초기화해야 한다.
  • state값을 변경할 때는 setState() 함수(상태 관리 함수)를 반드시 사용해야 한다.
  • setState() 함수는 비동기로 처리되며, setState() 코드 이후로 연결된 함수들의 실행이 완료된 시점에 화면 동기화 과정을 거친다.

위에서 보듯 state에 저장되는 객체는 반드시 초기화해야 하는데 그렇지 않으면 내부 함수에서 state 값에 접근할 수 없다. 만약 적당한 초기값이 없다면 state에 빈 객체라도 넣어야 한다.(this.state = {};) 또한 state에 저장되는 객체의 값은 직접 변경하면 안된다.


state 값은 setState() 함수로 변경한다.

state 값을 직접 변경하면 안 되는 이유는 render() 함수로 화면을 그려주는 시점은 리액트 엔진이 정하기 때문이다. 즉 state 값을 직접 변경하더라도 render() 함수는 새로 호출 되지 않는다. 하지만 setState() 함수를 호출하여 state 값을 바꾼다면 리액트 엔진이 자동으로 render() 함수를 호출하므로 화면에 변경된 state 값을 출력할 수 있다.


클래스 인스턴스 변수와 forceUpdate() 함수로 state 관리하기

하지만 무조건 setState()만이 방법이 아니다. 출력 검증 작업 없이 함수가 호출될 때마다 새롭게 화면을 출력하고 싶다면 클래스 인스턴스 변수와 forceUpdate() 함수를 사용하면 된다.

아래의 코드를 보자

import React from "react";

class ForceUpdateExample extends React.Component {
  constructor(props) {
    super(props);
    // 상태 정의
    this.loading = true;
    this.formData = "no data";
    // 이후 콜백 함수를 다룰때 bind를 선언하는 부분에 대해 다룹니다
    this.handleData = this.handleData.bind(this);
    // 생성 후 4초 후에 handleData를 호출합니다.
    setTimeout(this.handleData, 4000);
  }
  handleData() {
    const data = "new data";
    // 상태 변경
    this.loading = false;
    this.formData = data + this.formData;
    this.forceUpdate();
  }
  render() {
    return (
      <div>
        {/* 상태 데이터는 this.state로 접근 가능합니다. */}
        <span>로딩중: {String(this.loading)}</span>
        <span>결과: {this.formData}</span>
      </div>
    );
  }
}

export default ForceUpdateExample;

코드를 보면 컴포넌트 내장 함수 forceUpdate()를 호출하여 강제로 화면을 새로고침한다. 단, 이 방법은 리액트 성능에 제약이 있으므로 매번 새롭게 화면을 출력해야 되는 경우가 아니라면 가급적 사용하지 않는 것이 좋다.


참고 : Do it! 리액트 프로그래밍 정석

profile
개발이 즐겁고, 불편함을 해소해 줄 수 있는 개발자를 희망합니다.

0개의 댓글