본문 바로가기

Frontend/React

[React] useState batching, 비동기, 동기처리

728x90
useState의 두 가지 특이점에 대해서 기록하려고 한다.

 

 

두 가지 특징 모두 useState가 반환하는 세터 함수에 의해 일어나는 일이다.

Batch Update

  • state값의 업데이트는 16ms 단위로 이루어진다.
  • 16ms 내 변경된 state값은 한 번에 업데이트된다.
    • 때문에 setState 작업이 비동기적으로 작동하는 것이다.
import { useState, useEffect } from "react";

export default function App() {
  const [num, setNum] = useState(0);			//초기값을 0으로 한 state

  const handlePlus = () => {
    setNum(num + 1);					//기존 num 값에 1을 더하는 작업을 3번 함
    setNum(num + 1);
    setNum(num + 1);
  };
  return (
    <div>
      <p>{num}</p>					//num 값을 보여줌
      <button onClick={handlePlus}>plus</button>	//click 이벤트가 발생하면 handlePlus 함수 호출
    </div>
  );
}
  • 코드를 보면 plus 버튼을 눌렀을 때 당연히 3이 증가한 num 값이 보일 것이라고 생각된다.

  • 하지만 1씩 증가한 것을 볼 수 있다.
  • Batch Update가 되었기 때문이다.
  • setNum(num+1)코드에서 num 값은 세 번의 코드 모두 같은 초기값을 전달받기 때문에                                               결과값이 1이 되는 것이다.

비동기 작업

  • 앞서 언급한대로 세터 함수는 비동기적으로 작동한다.
  • 처음 useState를 배웠을 때 흔히 하는 실수가 있다.
import { useState, useEffect } from "react";

export default function App() {
  const [num, setNum] = useState(0);

  const handlePlus = () => {
    setNum(num + 1);
    console.log(num);						//증가한 num 값을 console에 출력
  };
  return (
    <div>
      <p>{num}</p>
      <button onClick={handlePlus}>plus</button>
    </div>
  );
}
  • 업데이트된 state 값이 콘솔에 출력될 것이라고 예상했을 것이다.

  • 하지만 세터 함수가 비동기적으로 작동하기 때문에 업데이트 되기 전의 num 값이 출력되었다.
  • 그렇다면 이러한 문제들을 어떻게 해결해야 할까?

 


함수형 업데이트

  • 먼저 앞서 연속적인 세터 함수의 사용으로 원하는 값을 얻지 못했던 문제부터 해결해보자.
  • 세터 함수에서 state값을 인자로 넘기는 콜백 함수를 사용해 값을 업데이트하면 된다.
import { useState, useEffect } from "react";

export default function App() {
  const [num, setNum] = useState(0);

  const handlePlus = () => {
    setNum((num) => num + 1);
    setNum((num) => num + 1);
    setNum((num) => num + 1);
  };
  return (
    <div>
      <p>{num}</p>
      <button onClick={handlePlus}>plus</button>
    </div>
  );
}

  • 위처럼 함수형 업데이트를 사용하면 업데이트된 state값을 인자로 받기 때문에 원했던 결과를 얻을 수 있다.

 

useEffect

  • useEffect의 Deps 배열을 사용하면 비동기적으로 처리되는 문제를 해결할 수 있다.
 

[리액트] React useEffect/componentDidMount/componentDidUpdate/componentWillUnmount

1. useEffect 역할 componentDidMount : 컴포넌트가 mount 된 직후의 작업을 해준다. componentDidUpdate : 컴포넌트에서 Update가 일어난 후에 작업을 해준다. componentWillUnmount : 컴포넌트가 mount되기 직전..

choi-records.tistory.com

import { useState, useEffect } from "react";

export default function App() {
  const [num, setNum] = useState(0);
  useEffect(() => {
    console.log(num);
  }, [num]);
  const handlePlus = () => {
    setNum((num) => num + 1);
  };
  return (
    <div>
      <p>{num}</p>
      <button onClick={handlePlus}>plus</button>
    </div>
  );
}
  • 위의 코드처럼 useEffect를 사용해서 deps 배열에 num을 추가했다.

  • num의 값이 업데이트되면 바로 console.log 함수가 실행되므로 업데이트된 state 값을 바로 볼 수 있다.
  • 이렇게 동기적으로 작동하는 작업들에서 업데이트된 state값을 사용하고 싶다면 useEffect를 사용하면 된다.
728x90