[TIL] useState의 함수형 업데이트

기성·2024년 8월 22일
1

TIL

목록 보기
43/81
post-thumbnail

우리는 보통 useState를 사용할 때 기본적으로

const [state, setState] = useState(0);

의 방식으로 사용한다. useState()의 인자로 초기값을 넣어주어 처음 상태의 값을 정할 수 있다. 또한 setter함수를 사용하여

setState(1);

상태를 변경을 시킬 수 도 있다. 하지만 항상 이렇게만 사용할 수 있는 것은 아니다.

이전 state를 기반으로 state 업데이트

state가 42라고 가정하고 handle에서 setState를 세 번 호출 해보자

function handleClick() {
  setState(state + 1); // setAge(42 + 1)
  setState(state + 1); // setAge(42 + 1)
  setState(state + 1); // setAge(42 + 1)
}

이 핸들러를 실행하면 state는 45가 되어있을까? 아니다. state는 43이다. 그 이유는 set함수를 호출해도 이미 실행중인 코드에서 state가 업데이트가 되지 않았기 때문에 setState(state+1)setState(43)이 된다.

이를 해결하기 위해서는 업데이터 함수를 전달할 수 있다.

function handleClick() {
  setState(a => a + 1); // setState(42 => 43)
  setState(a => a + 1); // setState(43 => 44)
  setState(a => a + 1); // setState(44 => 45)
}

setState안에 함수를 업데이터 함수라고 한다. 이 함수는 대기중인 state를 가져와서 다음 state를 계산하게 된다. React에서는 업데이터 함수를 에 집어 넣는데 넣고 나서 순서대로 호출하게 된다.

  1. a => a + 1은 대기 중인 state로 42를 받고 다음 state로 43을 반환한다.
  2. a => a + 1은 대기 중인 state로 43을 받고 다음 state로 44를 반환한다.
  3. a => a + 1은 대기 중인 state로 44를 받고 다음 state로 45를 반환한다.

이런 방식을 통해 이전 state를 업데이트 하고 싶다면 업데이터 함수를 사용하여 setter함수를 사용하면 된다.

초기값으로 무거운 작업이 존재할 때

state는 값이 변할 때 마다 리렌더링이 되는데

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

// 무거운 작업이라고 예시 들기
// 함수로 초기값 설정
const heavyWork = () => {
  console.log("렌더링 무거운 작업");
  return ["김누구", "이누구"];
};

export default function App() {
  const [names, setNames] = useState(heavyWork());
  //🚨 무거운 작업을 하는 함수를 초기값으로 바로 넣어버리기
  const [input, setInput] = useState("");

  const inputHandler = (e) => {
    setInput(e.target.value);
  };

  const buttonInputHandler = () => {
    setNames((prev) => {
      console.log("prev => ", prev);
      return [...prev, input];
    });
  };
  return (
    <div>
      <input type="text" value={input} onChange={inputHandler} />
      <button onClick={buttonInputHandler}>버튼</button>
      {names.map((name, idx) => {
        return <p key={idx}>{name}</p>;
      })}
    </div>
  );
}

요렇게 name state에 계속 추가하면서 값이 변경되면 리렌더링이 반복적으로 일어날 것이다.

이를 해결하기 위해서 어떻게 해야하느냐하면 useState()의 초기값을 넣어줄 때 함수를 바로 넣어 주는 것이 아니라 콜백함수로 넣어주게 되면

위 사진처럼 첫 렌더링에만 실행이 되고 리렌더시에 실행이 되지 않는 것을 확인할 수 있다. 이렇게 첫 상태로 무거운 작업을 넣게 된다면 바로 넣지않고 콜백형태로 집어넣어 첫 렌더링시에만 무거운 작업을 하도록 하게 하면 된다.

매번 사용하는 useState지만 함수형 업데이트는 생소하다. 이번 기회에 알게 되었으니 무거운 작업이라던지 이전 상태를 바로바로 사용하게 된다면 콜백과 업데이터 함수를 잘 적용해서 사용해 보도록 노력해야겠다.

profile
프론트가 하고싶어요

0개의 댓글