Andrii Radkevych
Andrii Radkevych

Reputation: 3422

How to memoize custom React hook

const useSomeHook = ({number}) => {
  const [newNumber, setNewNumber] = useState(0)

  useEffect(() => {
    setNewNumber(number + 1)
  }, [number])
}

const SomeComponent = ({number, value, ...restProps}) => {

  useSomeHook({number})


  return <div>{number}</div>
}

Let's imagine I have this case. Each time when in SomeComponent come some new prop, it will call my useSomeHook hook, but I want to prevent it. I want to call it only when the number is changed (memoize it). In other cases, don't touch it. But I haven't found any solving with this case. Could you help me solve this issue?

Upvotes: 25

Views: 31257

Answers (2)

Khaled Osman
Khaled Osman

Reputation: 1467

use useRef instead of useState to memoize/cache the returned value so that its not recomputed when its used across components, or when there are multiple instances of that component

const useSomeHook = ({number}) => {
  const numberRef = useRef(0)

  useEffect(() => {
    numberRef.current = numberRef.current + 1
  }, [number])
}

const SomeComponent = ({number, value, ...restProps}) => {

  useSomeHook({number})


  return <div>{number}</div>
}

it also sounds like you want to use useMemo instead of useEffect

const useSomeHook = ({number}) => {
  const numberRef = useRef(0)

  cachedValue = useMemo(() => {
    return numberRef.current + 1
  }, [number])
   return cachedValue
}

const SomeComponent = ({number, value, ...restProps}) => {

  const cachedValue = useSomeHook({number})


  return <div>{number}</div>
}

Upvotes: 3

Alex
Alex

Reputation: 1839

You can not prevent calling hook, this will lead to invariant violation error. Every hook in component should be executed on each render. You should rely on useEffect dependencies argument to run conditional code only if value changes.

Upvotes: 13

Related Questions