React 상태 관리: useState

Yerim Son·2023년 6월 29일
0

React

목록 보기
11/23

리액트는 절대 반복하지 않는다. 리액트는 응용프로그램이 처음 렌더링되었을 때 모든 과정(모든 컴포넌트를 지나 모든 함수들을 실행해서 화면에 그리는 것)을 실행하고 그 후에는 끝이다. 때문에 리액트에게 어떤것이 변경되었고, 특정 컴포넌트가 재평가되어야 한다고 말하는 방법이 필요하다. 그것이 바로 state라는 개념이다.

🌹 useState란?

  • useState는 React에서 제공하는 훅(Hook) 중 하나로, 함수형 컴포넌트에서 상태(state)를 관리할 수 있게 해준다.
    useState를 사용하여 상태를 선언하면, 리액트는 해당 상태를 컴포넌트 내에 저장하고 관리한다.

  • useState는 배열을 반환하는데, 첫 번째 요소는 현재 상태값
    이고, 두 번째 요소는 상태를 업데이트하는 함수.
    일반적으로 배열 구조 분해 할당을 사용하여 상태값과 상태를 업데이트하는 함수를 개별적으로 추출한다.

const [state, setState] = useState(initialValue);
  • state: 현재 상태값을 나타내는 변수. 컴포넌트가 초기화되거나 상태가 업데이트될 때마다 해당 변수에 저장된 값이 변경됨.
  • setState: 상태를 업데이트하는 함수. 이 함수를 호출하면 상태값이 변경되고, 리액트는 해당 컴포넌트를 리렌더링하여 변경된 상태를 반영함.
  • initialValue: 상태의 초기값을 설정하는 매개변수. 컴포넌트가 처음으로 렌더링될 때 사용되며, 이후에는 무시됨.

🌹 useState의 사용 조건

  1. 함수형 컴포넌트: useState는 클래스형 컴포넌트에서는 사용할 수 없다.

  2. 단일 상태값: useState는 단일 상태값을 관리하는 데 사용된다. 여러 개의 상태를 관리해야 할 경우, useState를 여러 번 호출하여 각각의 상태를 개별적으로 관리할 수 있다.

  3. 함수 내부에서 호출: useState는 함수 내부에서 호출되어야 한다. 함수 컴포넌트의 최상위 레벨에서 useState를 호출하여 상태를 선언해야 한다. 조건문, 반복문, 중첩 함수 등에서는 호출할 수 없다.

  4. 컴포넌트 렌더링 시 사용: useState는 컴포넌트의 렌더링 과정에서 사용된다. 즉, JSX 코드 내부에서 호출하거나 useEffect나 useCallback 등의 훅과 함께 사용할 수 있다.

  5. 상태값 변경이 필요한 경우: 상태값이 변하지 않고 고정적인 경우에는 useState를 사용할 필요가 없다. 단순히 값을 읽기만 하는 경우에는 useState 대신에 props나 컴포넌트 외부에서 전달받은 값을 사용하면 된다.

🌹 사용예시

  • ExpenseItem.js
import React from "react";
import Card from "../UI/Card";
import ExpenseDate from "./ExpenseDate";
import "./ExpenseItem.css";

const ExpenseItem = (props) => {

  let title = props.title; // let을 사용한 이유는 재할당..

  const clickHandler = () => {
    title = "updated!";
  };
  return (
    <Card className="expense-item">
      <ExpenseDate date={props.date} amount={props.amount} />
      <div className="expense-item__description">
        <h2>{title}</h2>
        <div className="expense-item__price">{props.amount}</div>
      </div>
      <button onClick={clickHandler}>change title</button>
    </Card>
  );
};

export default ExpenseItem;

위의 ExpenseItem 컴포넌트 함수는 처음에 렌더링된 후에 다시 호출되지 않는다.
왜냐면, 클릭했을 때나 변수가 바뀌었을 때는 이 컴포넌트 함수를 다시 실행하라고 트리거하지 않기 때문이다.

리액트에게 다시 실행하라고 말하려면 리액트 라이브러리에서 무언가를 import해야 한다.

import React from "react";

  • default import.
  • 전반적인 리액트 객체를 import.

import React, { useState } from "react";

  • named import (리액트 라이브러리에서 필요한 일부 라이브러리만 import)
  • useState라는 함수를 import

🌹 useState 복습

  • 컴포넌트 함수가 다시 호출되는 곳에서 변경된 값을 반영하기 위해 state로 값을 정의할 수 있게 해주는 함수.
  • 함수를 호출해서 새로운 값을 할당하는 것임.
  • 컴포넌트 함수 안에서 useState 함수를 호출해야 함.
  • 함수 밖이나, 중첩된 함수 안에서 호출할 수 없음!!!! (한 가지 예외가 있긴 함.. 그건 나중에)
  • react hook이라고 불림.
  const [title, setTitle] = useState(props.title);
	//const [현재 상태 값, 그것을 업데이트 하는 함수] = useState();

  • useState 사용
// ...

const ExpenseItem = (props) => {

  const [title, setTitle] = useState(props.title);

  const clickHandler = () => {
    console.log(title);
    setTitle("updated!!!"); //state를 update
  };
  
// ...

state가 변할 떄, 이 컴포넌트 함수를 다시 호출하고 싶으면 state를 업데이트하는 함수를 호출하면 된다.
여기서는 title이 변해야 하니 설정해둔 setTitle 함수를 호출, 변경하고 싶은 문자열을 입력했다.

변화하는 데이터를 갖고 있는데, 그 변화하는 데이터가 사용자 인터페이스에 반영되어야 한다면 state가 필요하다.
리액트는 state가 바뀌면 그 state가 등록된 컴포넌트를 다시 호출하고 재평가한다. 😄

🌹 구현 화면

  • State는 component의 instance별로 나뉘어져 있다.
  • 때문에 위의 ExpenseItem에 있는 change title 버튼 중 하나를 클릭하면 단 한 번만! 출력되는 것을 볼 수 있다.
  • 단지 그 특정 instance만 update 되었기 때문에 다시 리액트에 의해 평가된 것이고, 다른 인스턴스들은 상태 변화에 영향을 받지 않는다!

const 상수를 사용한 이유?

  • 등호 연산자(=)로 title에 새로운 값을 할당하지 않기 때문에 상수형(const)를 써도 괜찮다.

+ State는 여러 방법으로 업데이트 될 수 있다. ex) setTimeout();

  • + 항상 모든 상태를 문자열로 초기화(useState('')). 이유: 입력에 대해 변경 이벤트를 수신할 때마다, value of input in always String. 심지어 숫자를 저장해도 그것은 문자열로 된 숫자이고, 날짜도 마찬가지다. 그래서 여기서는 항상 문자열을 얻기 때문에 항상 모든 상태를 문자열로 초기화한다.

🌹 추가: useState의 비동기성과 함수형 업데이트의 중요성

const [insertToggle, setInsertToggle] = useState(false);

// 1.
setInsertToggle(!insertToggle);

// 2.
setInsertToggle((prev) => !prev);

위 중에 2번으로 쓰는 게 더 좋은 이유!

setInsertToggle(!insertToggle)setInsertToggle((prev) => !prev) 모두 동일한 동작을 수행하지만, 두 가지 방식의 차이가 있다.

  1. useState의 비동기성: useState는 비동기적으로 상태를 업데이트한다. 즉, setInsertToggle(!insertToggle)와 같이 현재 상태에 의존하여 새로운 상태를 계산하는 경우, 이전 상태값을 직접 참조할 때 문제가 발생할 수 있다. 이는 React가 상태를 일관되게 업데이트하기 위해 여러 setState 호출을 일괄 처리하기 때문이다. 그래서 이전 상태값을 사용하려면 함수 형태로 전달해야 한다.

  2. 함수형 업데이트의 안정성: setInsertToggle((prev) => !prev)와 같이 함수를 사용하는 경우, React는 항상 최신 상태값을 보장한다. 이 방식은 이전 상태값에 의존하는 경우에 특히 유용하다. prev 매개변수를 통해 항상 최신 상태값을 참조할 수 있기 때문이다.

따라서 함수 형태로 상태 업데이트 함수를 사용하는 것이 React 컴포넌트에서 상태 관리를 더 안전하게 할 수 있는 방법 중 하나이다.

0개의 댓글