Использование useMemo в кастомном хуке

Есть хук, который достает из контекста someData и внутри себя имеет несколько функций, использующих эту переменную из контекста, а затем группируются в один объект. Допустим, в объект utils:

const useSomeHook = () => {
  const {someData} = useContext(SomeContext);

  const [number, _setNumber] = useState(someData);
  const [randomNum, _setRandomNum] = useState(Math.random() * someData)
  
  const setNumber = (num) => {
    _setNumber(someData + num)
  }
  
  const setRandomNum = () => {
    _setRandomNum(Math.random() * someData)
  }
    
  const utils = {
    setNumber,
    setRandomNum
  }
  
  return {
    utils
  }
}

И этот хук используется в ParentComponent для передачи utils в качестве пропса для ChildComponent:

const ParentComponent = () => {
  const {utils} = useSomeHook();
  const [parentData, setParentData] = useState(null);

  return <ChildComponent utilsProp={utils} parentData={parentData} />
}

Насколько я понимаю, одного React.memo() будет мало для того, чтобы избежать лишних ререндеров ChildComponent из-за того что объект utils из хука может "пересобираться" потому что имеет в себе функции, изменяющие состояние хука и использующие данные из контекста, которые так же могут меняться. Я попытался мемоизировать этот объект подобным образом:

const utils = useMemo(() => ({
  setNumber,
  setRandomNum
}), [setNumber, setRandomNum]);

И меня мучает вопрос: а стоит ли функции setNumber и setRandomNum обернуть так же в useCallback, а затем как зависимость указать someData, которая приходит из контекста? Или это уже избыточное движение?


Ответы (1 шт):

Автор решения: MrYogurt

Давайте для начала разберемся, что такое хук. Хук, это импортабельный компонент, для многократного переиспользования. При импортировании, создается его копия (инстанс), следовательно ваш хук будет уникален для каждого компонента, в котором он используется. Также я вижу, что хук берет данные из контекста, с которыми проводит операции, следовательно нет смысла его вообще мемоизировать, ибо он неизбежно должен ререндериться при изменении стейтов, но ререндерится будет только он сам, не затрагивая родительский компонент, в который импортируется.

→ Ссылка