React - 상태관리 State

YongWan·2023년 3월 9일
0

React Basic

목록 보기
5/10
post-thumbnail

useState 사용법

React에서 UI와 밀접하게 관련있는 데이터는 State에 보관해줘야 한다.

잘못된 예

// 로컬변수를 전달하고 업데이트 해도 React에서 인식하지 못한다.
export default function Counter() {
  let num = 0;
  return (
    <div className="counter"> 
      <span className="number">{num}</span>
      // console로 출력해보면 num은 1씩 증가하지만 UI에는 변화가 없다.
      <button className="button" onClick={() => {num++; console.log(num)}}>Add +</button>
    </div>
  );
}

올바른 예

// useState는 변경 가능한 value와 value를 업데이트 할 수 있는 function을 리턴한다.
import React, { useState } from "react";

export default function Counter() {
  // useState(0)로 초기값을 설정하면 배열을 리턴한다. 
  // 배열에는 상태를 확인할 수 있는 let count, 상태를 업데이트 해주는 function setCount
  // 통상적으로 function에는 set키워드를 붙힌다.
  const [count, setCount] = useState(0);
  return (
    <div className="counter"> 
      <span className="number">{count}</span>
      // onClick이벤트가 발생하면 React는 변경된 값의 함수 전체 즉 Counter컴포넌트를 re-render한다.
      // virtual DOM을 통해 이전 DOM요소와 비교 후 변경된 부분만 업데이트 해준다.
      // re-render되어도 useState에서 이전 값을 기억하고 있기 때문에 0으로 초기화 되지 않는다.
      <button className="button" onClick={() => {setCount(count + 1)}}>Add +</button>
    </div>
  );
}

useState 주의사항

만약 아래와 같이 setCount(count + 1)를 5번 작성하면 어떻게 동작할까?

import React, { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div className="counter"> 
      <span className="number">{count}</span>
      <button className="button" onClick={() => {
        setCount(count + 1);
        setCount(count + 1);
        setCount(count + 1);
        setCount(count + 1);
        setCount(count + 1);
      }}>Add +</button>
    </div>
  );
}

결과는 5씩 증가가 아닌 1씩 증가한다.
이는 Javascript 클로저와 밀접한 관련이 있다.
onClick 이벤트 발생으로 전달되는 콜백함수는 전달 될 때의 상태를 기억한다.
즉 count의 초기값 0을 기억하게 되고 setCount(count + 1)를 5번 실행해도 5번 모두 0 + 1이 되는 것이다.
즉 마지막 실행한 setCount(count + 1)이 최종 값이 된다.

만약 5번 실행한 setCount(count + 1)값이 누적 되길 바란다면
콜백함수를 통해 이전 상태값을 파라미터로 전달하여 누적된 결과값을 출력할 수 있다.

올바른 예

아래와 같이 setCount((prev) => prev + 1)로 작성해야 event 발생 시 5씩 증가하게 된다.

import React, { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div className="counter"> 
      <span className="number">{count}</span>
      <button className="button" onClick={() => {
        // 이전 상태값 prev 0
        setCount((prev) => prev + 1);
        // 이전 상태값 prev 1 
        setCount((prev) => prev + 1);
        // 이전 상태값 prev 2 
        setCount((prev) => prev + 1);
        // 이전 상태값 prev 3 
        setCount((prev) => prev + 1);
        // 이전 상태값 prev 4 
        setCount((prev) => prev + 1);
        // 최종 상태값 5 
      }}>Add +</button>
    </div>
  );
}

0개의 댓글