React의 setState() 제대로 사용하기

🐶·2021년 7월 17일
1

개념 정리

목록 보기
26/41
post-thumbnail
post-custom-banner

setState()

setState()는 리액트의 함수형 컴포넌트 내에서 상태를 관리하기 위해 사용하는 hooks인 useState()를 통해 반환되는 함수이다.

setState()의 특징

1. 기본적으로 비동기로 동작한다.
2. 연속적으로 호출했을 때 리액트 내부적으로는 BATCH 처리를 한다.
3. state 객체를 넘겨줄 수 있을 뿐만 아니라 새로운 state를 반환하는 함수를 인자로 넘겨줄 수 있다.

기본적으로 setState()함수는 state를 변경하고 state가 포함된 해당 컴포넌트를 다시 렌더링한다. 그런데 이게 동기적으로 동작하는 것이 아니라 비동기적으로 동작함에 주목해야한다(= setState()를 실행하자마자 바로 state를 변경하고 바로 렌더링하는게 아니다!).

setState()가 연속으로 여러번 호출된다면...?

리액트는 state가 업데이트 되기 이전, 현재의 state값으로 만든 element tree와 업데이트된 state값으로 만든 element tree를 비교한 다음, 최종적으로 변경된 부분이 있으면 그걸 DOM에 적용하는 과정을 거친다 --> 상당히 번거로움.

따라서 이 과정을 한 번에 할 수 없을까? 생각하게 되고 setState()가 연속으로 두 번 호출되면 각 함수 호출 시 전달받은 각각의 state를 merging하는 작업을 수행하게 된다. 그 후 state의 변경을 반영하는 setState()는 한 번만 호출한다.

예시 코드

import React, { useState } from "react";
import "./styles.css";

export default function App() {
  const [number, setNumber] = useState(1);

  const add = () => setNumber(number + 1);
  const subtract = () => setNumber(number - 1);
  const multiplyBy2 = () => setNumber(number * 2);
  const multiplyBy2AndAddBy1 = () => {
    multiplyBy2();
    add();
  };

  return (
    <div className="outer-wrapper">
      <h1>Number : {number}</h1>
      <div className="btn-wrapper">
        <button onClick={add}>+ 1</button>
        <button onClick={subtract}>- 1</button>
        <button onClick={multiplyBy2}>*2</button>
        <button onClick={multiplyBy2AndAddBy1}>*2 + 1</button>
      </div>
    </div>
  );
}

merging이 동작하는 원리


--> state는 사실 객체이다. 초기 number값을 그대로 유지한 채로 객체가 overwrite된다

setState()의 전달인자


setState()의 전달인자는 두 종류가 들어갈 수 있다.
1. state가 어떻게 변경되어져야 한다라는 그 값을 넣을 수도 있고(S)
2. ((prevState: S) => S) 즉 이전의 state를 인자로 받고 새로운 state를 반환하는 함수를 넣을수도 있다

문제를 해결한 코드

따라서 아래와 같이 setNumber함수의 전달인자를 함수형태로 변경시켜주었다.

const add = () => setNumber(number => number + 1); 
//2. 그 다음에 넘겨받은 인자의 함수도 아까 그 큐에 넣는다.
  const subtract = () => setNumber(number => number - 1);
  const multiplyBy2 = () => setNumber(number => number * 2); 
//1. setNumber가 함수를 넘겨받으면 이걸 나중에 실행 해야지 하고 큐라는 구조를 가지고 있는 저장 공간에 넣는다. 
  const multiplyBy2AndAddBy1 = () => {
    multiplyBy2(); 
    add();
  }; 
//3. queue는 먼저 들어온 함수부터 실행시키는데(선입선출), 1을 실행하고 새로운 값 반환(number = number*2)하고, 
//그 다음 함수의 인자로 넘겨주는 동작을 하게 된다.

setState()가 비동기로 동작한다는 사실은 변함이 없지만, 동기적으로 처리되는 것처럼 보이는 것...!

참고자료
https://leehwarang.github.io/2020/07/28/setState.html
https://www.youtube.com/watch?v=hSdVDBPTT0U&t=1s
https://usecode.pw/functional-set-state-is-the-future-of-react/

profile
우당탕탕 개발일기📝🤖
post-custom-banner

1개의 댓글

comment-user-thumbnail
2023년 3월 21일

잘보고갑니다 !!

답글 달기