Hooks
date
Feb 13, 2023
slug
react-hooks
author
status
Public
tags
React
summary
type
Post
thumbnail
category
updatedAt
Jan 15, 2024 12:34 PM
Hook?
React의 Hook은 React 함수형 컴포넌트에서 상태(state)와 라이프사이클 메소드(lifecycle methods)를 사용할 수 있도록 하는 기능입니다.
Hook은 기존의 클래스 컴포넌트에서만 사용할 수 있었던 기능들을 함수형 컴포넌트에서도 사용할 수 있게 해주며, 함수형 컴포넌트를 보다 간결하고 유지보수가 쉽도록 만들어 줍니다.
Hook 규칙
- 컴포넌트의 최상위 레벨에서만 호출해야합니다.
- 반복문이나 조건문 혹은 중첩 함수 내에서 Hook을 호출하면 안됩니다. -> 리액트 훅은 호출 순서에 의존하기 때문에 조건문이나 반복문 내부에서 실행할 경우 해당 부분을 건너뛰는 일이 발생하는 등의 버그가 발생할 수 있습니다.
- 리액트 함수 내부에서만 호출해야합니다.
useState
React에는 다양한 Hook이 있지만, 가장 기본적인 것은 useState Hook입니다.
useState
는 함수형 컴포넌트에서 상태를 관리하는 데 사용되는 훅입니다.
useState
훅은 배열을 반환하며, 첫 번째 요소는 현재 상태 값이고, 두 번째 요소는 상태 값을 변경하는 함수입니다.예를 들어, 다음과 같은 코드를 작성할 수 있습니다.
import React, { useState } from 'react'; function Example() { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
위 코드에서
useState
훅은 count
변수와 setCount
함수를 생성합니다.
count
변수는 초기값으로 0
을 가지고 있으며, setCount
함수는 count
변수를 업데이트합니다.
setCount
함수는 새로운 값을 전달받아 해당 값으로 count
변수를 업데이트합니다.useState
훅을 사용하면, 함수형 컴포넌트에서 상태 값을 관리할 수 있습니다.
이를 통해, 컴포넌트가 렌더링될 때마다 새로운 상태 값을 생성하고 관리할 수 있습니다.
또한, 상태 값을 업데이트하는 방식도 간단하고 직관적입니다.이 쌍의 이름은
const [something, setSomething]
과 같이 지정하는 것이 일반적입니다.React는 어떤 state를 반환할지 어떻게 알 수 있을까요?
useState
에 전달되는 “식별자”가 없는데 어떤 state 변수를 반환할지 어떻게 알 수 있을까요?
내부적으로 React는 모든 컴포넌트에 대해 한 쌍의 state 배열을 가집니다.
또한 렌더링 전에 0
으로 설정된 현재 쌍 인덱스를 유지합니다.
useState
를 호출할 때마다 React는 다음 state 쌍을 제공하고 인덱스를 증가시킵니다.
이 메커니즘에 대한 자세한 내용은 React Hook: 마법이 아니라 배열일 뿐입니다 에서 확인할 수 있습니다.useState 자세히 뜯어보기
- useState같은 Hook들은 react 모듈 안에 선언된 함수입니다.
- useState는 실행될 때마다 dispatcher를 선언하고 useState 메서드를 실행해서 그 값을 반환합니다.
- 선언한 dispatcher코드를 살펴보면 전역 변수 ReactCurrentDispatcher로부터 dispatcher를 가져옴을 확인할 수 있습니다.
함수가 선언부(dispatcher)보다 상위에 있는 값(ReactCurrentDispatcher)에 접근하고 있습니다.
여기서, Closure의 개념이 등장하게 됩니다.
👆 useState는 _value 라는 전역에 선언된 변수를 참조하고 있습니다.
이것이 바로 우리가 관리하는 ‘state'에 해당합니다.
자신이 선언된 위치에서 접근할 수 있는 _value 상태를 변경하는 것입니다.
if(_value === undefined) _value = initialValue;
👆 최초 호출에만 초기값을 할당하고 이후에는 initialValue가 아예 사용되지 않습니다.
동작 과정을 흝어보자면...
- 처음 컴포넌트 함수가 실행되어 useState를 실행합니다. 👉 _value가 undefined이니 initialValue를 할당합니다.
- 다시 컴포넌트 함수가 실행되면 useState가 실행됩니다. 👉 이 때에는_value가 undefined가 아닙니다.
- useState가 반환한 값을 변수에 할당합니다.
- setState함수는 자신과 함께 반환된 변수를 변경시키는 것이 아니라
다음 useState가 반환할
react 모듈의 _value를 변경
시키고 컴포넌트를 리렌더링 시키는(트리거) 역할을 합니다.
변경된 값은 다음 컴포넌트 함수가 실행될 때 useState가 가져오기 때문에
setState 호출 이후 로직에서도 state의 값은 이전과 동일합니다.
다음 렌더링 전에 동일한 state 변수를 여러 번 업데이트하기
흔한 사례는 아니지만, 다음 렌더링 전에 동일한 state 변수를 여러 번 업데이트 하고 싶다면
setNumber(number + 1)
와 같은 _다음 state 값_을 전달하는 대신, setNumber(n => n + 1)
와 같이 큐의 이전 state를 기반으로 다음 state를 계산하는 _함수_를 전달할 수 있습니다.
이는 단순히 state 값을 대체하는 것이 아니라 React에게 “state 값으로 무언가를 하라”고 지시하는 방법입니다.import { useState } from 'react'; export default function Counter() { const [number, setNumber] = useState(0); return ( <> <h1>{number}</h1> <button onClick={() => { setNumber(n => n + 1); setNumber(n => n + 1); setNumber(n => n + 1); }}>+3</button> </> ) }
updator function 사용하기
여기서
n => n + 1
는 업데이터 함수(updater function) 라고 부릅니다. 이를 state 설정자 함수에 전달 할 때- React는 이벤트 핸들러의 다른 코드가 모두 실행된 후에 이 함수가 처리되도록 큐에 넣습니다.
- 다음 렌더링 중에 React는 큐를 순회하여 최종 업데이트된 state를 제공합니다.
업데이터 함수 인수의 이름은 해당 state 변수의 첫 글자로 지정하는 것이 일반적입니다.
setEnabled(e => !e); setLastName(ln => ln.reverse()); setFriendCount(fc => fc * 2);