[React] useDeepMemo

Joonas' Note

[React] useDeepMemo 본문

개발/Javascript

[React] useDeepMemo

2025. 4. 15. 00:22 joonas 읽는데 1분
  • 참고

primitive 하게 비교되지 않는 object들은 의존성 배열에서 같은 값으로 인식하지 않는다.
이건 javascript 의 비교 연산자가 얕은 비교를 하기 때문이다. 아래는 대표적인 사례.

{} == {}
// output: false

즉, 아래의 memo는 전혀 캐싱되지 않기 때문에 어떤 스노우볼을 굴릴 지 모른다.

const complexObject = {a:1, b:2, c:"xyz"}
// 의존성 배열은 항상 다른 값으로 인식된다.
const complexMemo = useMemo(() => complexObject, [complextObject])

아래와 같이 비교 대상을 문자열로 변경해서 해결하는 방법도 있는데, 보기에도 느껴지지만 그렇게 권장되는 방법은 아니다.

const complexObject = {a:1, b:2, c:"xyz"}
const complexMemo = useMemo(() => complexObject, [JSON.stringify(complextObject)])

위 방법과 크게 다르지 않지만, 핵심은 의존성 배열 내의 객체를 비교해야 하는 것이므로, 구조적으로 변경할 수 있게 아래처럼 작성해서 사용하고 있다.

// useDeepHooks.ts
import { useRef, useEffect, useMemo } from 'react'

const serialize = (obj: any) => {
  if (typeof obj === 'object') {
    return JSON.stringify(obj)
  }
  return obj
}

export function useDeepMemo(callback: () => any, dependencies: any[]) {
  const depsStringified = useMemo(
    () => dependencies.map(serialize),
    dependencies,
  )
  return useMemo(() => callback(), depsStringified)
}

리액트 개발자 중 한 명은 이 외에도 2가지 방법을 더 제시하고 있다.

그 외에도 ref 를 사용해서 상태를 들고 있는 방법도 있는데, Object 비교에서 실수한건지 제대로 동작하진 않았다.

참고

 

When to useMemo and useCallback

Stay up to date Stay up to date All rights reserved © Kent C. Dodds 2025

kentcdodds.com

 

useCallback/useEffect support custom comparator · Issue #14476 · facebook/react

Currently we can pass an array as second argument when using useCallback or useEffect like below: useCallback(()=> { doSth(a, b) }, [a, b]) // how to do deep equal if a is an object ? The problem i...

github.com

 

Comments