ReactJS component useeffect hooks call every time parents get updated

795 views Asked by At

I have a parent component.

function ParentComponent(){

  return (
     //loading is asynchronous variable which changes on some event call.
    {loading ? ( 
     <ChildComponent></ChildComponent>
    ): (
     <div>Some text...</div>
    )} 
  )
}

and a child component

function ChildComponent(){

  useEffect(() => {
     console.log("render child component"); 
  }, [])

  return (
     <div>This is child component</div>
  )
}

The problem is that whenever loading state changes to true the child components useEffect hooks get calls every time time even though i am passing [] array as the second argument of useEffect hook. However useEffect works perfectly if i remove the condition and then change the loading state.

2

There are 2 answers

0
Dmytro Krasnikov On BEST ANSWER

Ok, what you have here is conditional loading. Once your loading state changed to false - your component will be removed from DOM and all the cleanup work performed. Once loading state changed from false to true - your component will be added and all initialization work will happen (useState will also set initial value, etc.). You can try to update your hook to see what is going on. Also please check useEffect docs

function ChildComponent(){

  useEffect(() => {
     console.log("render child component"); 
     return () => console.log("cleanup");
  }, [])

  return (
     <div>This is child component</div>
  )
}

So my suggestion, that you really don't want to remove component from the DOM, so you need just not to show it

function ParentComponent(){

  return (
     //loading is asynchronous variable which changes on some event call.
     <ChildComponent style={{display: loading? 'block' : 'none' }}></ChildComponent>
    { !loading && <div>Some text...</div> } 
  )
}
0
Dinesh Kumar On

You should pass loading state through props and use it in useEffect.

Parent Component:

function ParentComponent(){

  return (
     //loading is asynchronous variable which changes on some event call.
    {loading ? ( 
     <ChildComponent loading={loading}></ChildComponent>
    ): (
     <div>Some text...</div>
    )} 
  )
}

Child component:

function ChildComponent(loading){

  useEffect(() => {
     console.log("render child component"); 
  }, [loading])

  return (
     <div>This is child component</div>
  )
}