How does React hook handle dependency lists when passing objects to child components?

Parent component like this:

function ParentComponent(){
  return (
    <ChildComponent data={{ x: 1, y: 2 }} />
  )
}

Child component like this:

function ChildComponent({ data }){
  const [sum, set] = useState(0)
  
  useEffect(() => {
    set(data.x + data.y)
  }, [data])

  return (
    <div>{sum}</div>
  )
}

If it is like the above method, it will cause repeated rendering between subgroups, because the data is always changing. How should I deal with such a scenario?

Of course I know it's possible to cache data in the parent component by const [data] = useState({ x: 1, y: 2 }), but I want to know if there is a better solution, if any object parameter is required useState to cache, is this implementation too complicated?

In addition, it can also be stored in the child component through const dataRef = useRef(data), but if a value of data changes, it will not be recalculated.

Other parameters such as functions and arrays are the same.

What's wrong with my thinking?

1 answer

  • answered 2022-05-07 02:56 CertainPerformance

    if any object parameter is required useState to cache

    Luckily, the dependency array can contain any value - not just objects. Because you're using what's being passed down as

    set(data.x + data.y)
    

    you could set the dependency array to just those properties, rather than the whole object:

      useEffect(() => {
        set(data.x + data.y)
      }, [data.x, data.y])
    

    or even

      useEffect(() => {
        set(data.x + data.y)
      }, [data.x + data.y])
    

    Alternatively - in React, when you want to keep things in sync, it's often easier (and cleaner) not to duplicate state / props in multiple components when possible. For example, if something's being passed down as a prop, if you can just use the prop, rather than also putting the prop into state, that can be the easier approach than the alternative. I know this was just a toy example, but it's not an uncommon pitfall.

    function ChildComponent({ data }){
      return (
        <div>{data.x + data.y}</div>
      )
    }
    

    (If the operation to be performed is expensive, and you don't want to perform it on every render, memoize the value instead of putting it into state)

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum