개인공부

[React] useState(value) vs useState(callbackFn)

chsua 2023. 12. 28. 01:08

배경

토스 슬래시 중 useOverlay를 읽으며 의문이 들었다.

let elementId = 1;

export function useOverlay({ exitOnUnmount = true }: Options = {}) {

    ...(중략)

    const [id] = useState(() => String(elementId++));

    ...(중략)

나는 항상 useState를 사용할때 값을 넣어서 사용을 했다.
id를 전역으로 관리하는 것하며,
초기값으로 함수를 넣는 것이 무엇을 의미하는지 궁금해졌다.

 

 

 

같은 원리의 쉬운 코드 제작

stackblitz를 통해 코드를 만들어봤다.

구조는 아래와 같다.

  1. 앱 안에 엘리먼트 컴포넌트가 2개 들어있다.
  2. 앱과 엘리먼트 컴포넌트에는 각각 hook이 호출된다.
  3. hook은 초기값이 콜백으로 들어가있는 callbackId와 그냥 값이 들어가있는 justId가 상태로 있다.
  4. 앱 내 엘리먼트 컴포넌트는 조건없이 계속 렌더링되어있는 컴포넌트와 count조건에 따라 등장/삭제되는 컴포넌트로 구분된다.
  5. 앱 내 카운터는 리렌더링을 위한 트리거이다.

여기서 이렇게 저렇게 만진 결과는 아래와 같다.

  1. +/- 버튼을 눌렀을 때 count가 바뀐다.
    • 앱 내 id들과 조건없는 엘리먼트 컴포넌트 내 id들은 변화가 없다
    • 조건있는 엘리먼트 컴포넌트는 조건(짝수인 경우 렌더링)에 따라 등장/삭제가 반복된다.
      • 렌더링될때마다 id 값이 변화한다.
  2. 코드의 순서를 바꾸는 등 코드를 수정했을 때 카운터 상태는 날아가지만 id 정보는 날아가지 않는다.

 

 

분석 결과

  1. 해당 블로그에서는 useState(callbackFn)는 리렌더링에서 재실행되지 않는다고 한다. 이때문에 카운터를 조작해 조건있는 엘리먼트가 렌더링될 때 callback을 넣은 id와 값을 넣은 id가 확연히 증가률이 다름을 알 수 있다.
    • 카운터를 조작한다 > 리렌더링이 된다 > callback을 넣은 경우에는 callback이 재실행되지 않는다 / 값(여기선 함수)을 넣은 경우에는 실행된다.
  2. 코드의 순서를 바꾸는 것은 리액트 내 함수 트리를 다시 조정하는 일이다. 전역으로 관리되는 변수는 다시 실행되지 않으니 코드가 변경되더라도 변경되지 않는다.

 

 

chatGPT

> useState의 초기값으로 함수를 사용하는 이유는 주로 초기값이 복잡한 계산이나 외부 데이터에 의존하는 경우, 렌더링마다 계산되는 것을 방지하고 성능을 최적화하기 위함입니다. React에서 useState를 사용할 때 초기값은 해당 상태가 최초로 생성될 때만 호출됩니다. 만약 초기값으로 함수가 아닌 값을 직접 제공한다면, 그 값은 컴포넌트가 렌더링될 때마다 계산되고 새로운 상태로 설정됩니다. 이는 상태의 값이 변하지 않는 경우에도 불필요한 계산과 렌더링이 발생할 수 있습니다. 함수를 사용하면 컴포넌트가 처음 렌더링될 때만 초기값을 계산하고, 이후 렌더링에서는 해당 함수를 호출하지 않습니다. 이를 통해 성능 향상이 이루어집니다.

> 함수 컴포넌트 내부에서 useState 훅을 호출할 때마다 해당 상태를 관리하고, 초기값을 제공할 때 함수가 호출되어 최초 상태를 설정합니다. 초기값을 함수로 제공함으로써, React는 최초 렌더링 때만 함수를 호출하여 초기값을 설정하고, 이후 렌더링에서는 함수를 다시 호출하지 않고 이전에 설정된 상태를 유지합니다.

 

 

 

추측하기로 그 안에 그냥 함수가 있으면 바로 실행되어 결과값을 상태로 저장하지만, 콜백으로 넣으면 콜백으로 저장했다가 실행하여 그 결과를 저장하는 것 같다. 단순하게 생각하니 함수에 인자를 넣는 방식과 동일한 원리라고 생각든다. 이런 저런 이유를 찾는데 시간이 오래 걸렸는데 정리하고 보면 늘 별거 없는 것 같다.
코드 사이트에 들어가서 포크해서 직접 만져보면서 익혀보면 좋을 것 같다.