Search code examples
reactjsreact-hooksinfinite-loopuse-effect

Infinity loop when using useEffect while try to update children component


I am trying to update components when the parent component passes down the change to the children through props, so I create a test program like so

PARENT COMPONENT

   function Parent(props){
     const [newCount, setNewCount] = useState(0)
     const handleClick = (event)=>{
        event.preventDefault()
        setNewCount(count+1)
     }
     return <div>
                 <button className='btn btn-primary' type='submit' onClick={handleClick}>parent</button>
                 <Test newCount = {count}/>
            </div>
}

CHILDREN COMPONENT

function Test(props){
    const [count, setCount] = useState(0)
    const {newCount} = props
    useEffect(()=>{
        setCount(count + 1) ### marked line
    },[newCount, count])
    return <button type='submit'>{count}</button>
}

whenever the parent's button got clicked the children will be re-rendered base on the "newCount" value passed from its parent. I can understand that the line marked with "###" will cause an infinite loop, but what make me confuse is if I replace setCount(count+1) with setCount(newCount+1) then I don't get infinite loop anymore. Can some want help me explain why? thank you in advance


Solution

  • You have added count as a dependency to useEffect which in itself updates count, so the useEffect gets triggered in a loop

    useEffect(()=>{
        setCount(count + 1) ### marked line
    },[newCount, count]); // problem due to use of count here
    

    When you change to setCount(newCount + 1), you would be removing the dependency count from useEffect and hence it no longer causes an infinite loop

    Since you want to update the child state based on parent, you must actually be using

    useEffect(()=>{
        setCount(newCount) ### marked line
    },[newCount]);
    

    However you can directly use the count value from props and update the same by passing an updater function from parent as props without the need to copy into local state

    P.S. Probably its just a typo in post, but in the parent you need to use newCount and not count while updating state since count is not defined in parent

    const handleClick = (event)=>{
        event.preventDefault()
        setNewCount(newCount+1)
     }