bread-gee 2023. 12. 5. 16:37

시작하기 전...

HOOK

  • React 버전 16.8부터 도입된 기능
  • 함수형 컴포넌트에서 상태(state)와 생명주기(lifecycle) 기능 등을 사용할 수 있도록 하는 기능
  • 훅은 use로 시작한다.
  • 훅들은 리액트 컴포넌트 함수 안에서 호출되어야 한다.

🔥함수형 컴포넌트 기반으로 정리를 했습니다!

 

useState 훅을 이용하면 컴포넌트에서 상태를 추가하고 관리할 수 있다.

 

컴포넌트 내에서 변수를 선언하면, 해당 변수의 값이 변경되어도 React는 컴포넌트를 다시 렌더링하지 않는다.

React는 컴포넌트의 상태나 props가 변경되었을 때에만 다시 렌더링을 수행한다. 이것이 React의 "재평가" 개념이다.

 

useState를 사용하여 상태를 선언하면, React가 해당 상태를 추적하고, 상태가 변경될 때마다 컴포넌트를 리렌더링한다.

 

📌 기본형 

import { useState } from 'react';

const [count, setCount] = useState(0);

 

useState는 배열을 반환하며, 배열의 첫 번째 요소는 현재 상태의 값이고, 두 번째 요소는 상태를 업데이트하는 함수이다.

 

📌 상태 업데이트

setCount(count + 1);

setCount로 count를 변경하면, count는 아직도 이전 값을 가지고 있다.

 

  • state를 업데이트 하는 함수를 호출했을 때 사실상 바로 값을 바꾸지 않았기 때문이다.
  • 대신 state의 없데이트를 예약한다.
  • 화면이 리렌더링되어 JSX가 다시 호출되면 재평가되어 업데이트 된 값을 볼 수 있다.

 

📌 즉시 반영 방법

🌀 숫자 사용 시

setCount((prevCount) => prevCount + 1);

이전 상태를 사용하여 업데이트를 수행한다.

 

🌀 문자 사용 시

setText((prevText) => 'Next Text');

setText 함수에 전달된 함수는 항상 'Next Text'를 반환하므로 새로운 상태로 업데이트 된다.

prevText를 명시적으로 사용할 필요가 없다. 이전 상태를 기반으로 하는 경우에만 prevText 등의 이름을 사용하면 된다.

 

 

📌 사용 방법

🌀 독립적 state 관리

하나의 컴포넌트에서 여러 개의 state 정의가 가능하다.

// [정의]
const [enteredTitle, setEnteredTitle] = useState('');
const [enteredAmount, setEnteredAmount] = useState('');
const [enteredDate, setEnteredDate] = useState('');

// [사용]
setEnteredTitle((prevText) => 'Next Text');

 

 

 

🌀 한번에 여러 state 관리

중복된 부분을 제거한다.

useState 하나에 여러 state를 묶어준다.

  • 객체형 / 수동으로 업데이트
    • 한가지만 변경해도 나머지를 다시 업데이트 해야 한다.
    • 스프레드 연산자를 넣지 않으면, enteredAmount와 enteredDate는 변경된 값이 들어있어도 다시 빈값('')으로 초기화 해버린다.
// [정의]
const [userInput, setUserInput] = useState({
	enteredTitle: '',
	enteredAmount: '',
	enteredDate: '',
});

// [사용]
setUserInput({
	...userInput, // 기존 변수 3개 복사 후
	enteredTitle: event.target.value // 얘만 덮어쓰기
});

 

 

 

[여기서 궁금한 것!]

값을 복사하기 위해 이전 state를 고려해야 할 때, 어떻게 상태를 업데이트해야 할까?

 

  • 함수형 / 자동으로 업데이트
    • 상태를 업데이트하는 폼에선 다른 방식 적용한다.
    • 객체 형식으로 전달하는 대신 함수를 호출해서 함수를 전달해야 한다.
    • setUserInput 함수를 호출해서 이전 상태의 스냅샷인 prevState를 매개변수로 가지고 있는 다른 함수를 전달한다.
// [정의] 위와 동일
// [사용]
setUserInput((prevState) => {
	// 새로운 스냅샷 반환
	return { ...prevState, enteredTitle: event.target.value };
});

/*
여기서 prevState의 내용은
    {
        enteredTitle: '',
        enteredAmount: '',
        enteredDate: '',
    }
*/

 

 

📌 왜 함수형으로 호출할까?

  • 리액트는 상태 업데이트 스케줄을 갖고 있어서 바로 실행하지 않는다.
  • 이론적으로 동시에 수많은 상태 업데이트를 계획한다면, 오래되었거나 잘못된 상태 스냅샷에 의존할 수도 있다.
  • 객체형으로 작업한다면, 상태들을 수동으로 관리해야 하는 불편함이 있다.
  • 함수형을 사용하면, 함수 내에서 항상 최신의 state 스냅샷 사용하고, 항상 계획된 상태 업데이트를 염두에 두고 있다는 것을 보장한다.