26
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?

5
  • 2
    The useEffect hook within useSomeHook will only be invoked when the dependency number changes. Commented Apr 26, 2020 at 9:43
  • 1
    So I don't see what memoization gives you in this case. Commented Apr 26, 2020 at 9:44
  • In this case it will be ok, but imagine that I have some hard logic in this hook, and it invoked each time for example I type something with redux form , and it works horrible Commented Apr 26, 2020 at 9:58
  • What you pass in the second argument for useEffect will trigger subsequent invocation of the callback you pass in as the first argument. To address your ask, you can do two things: 1. Add in-depth equality check as the second param (this requires some work), and/or 2. Add a condition in the callback; ex: if (obj.a !== obj.b) callback() Commented Jun 4, 2021 at 17:10
  • use useRef instead of useState Commented Apr 28, 2023 at 10:07

2 Answers 2

13

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.

Sign up to request clarification or add additional context in comments.

Comments

3

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>
}

2 Comments

what if our useSomeHook is making an api call, it that case useRef might not be a good thing to use as well, thoughts ?
@Prateek Why not? I would argue that using useRef especially when making api calls is even better because you can use it to cache the api call response, otherwise if you use the same hook across multiple components, you would be making multiple api calls

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.