Reputation: 437
Sorry, reactjs beginner here, with below two codes, I don't get why when I use the "First code" I get infinite loop (infinite log out '123' in my browser console) and when I use "Second code", I don't get infinite loop (only log out two '123' in my browser console), how come I am not getting infinite loop with "Second code" when I am getting infinite loop with my "First code"?
(First code) Cause infinite loop:
[Parent.js]
const randomFunc = (dataFromChildComponent) => {
setData(dataFromChildComponent);
};
[Child.js]
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/posts")
.then((response) => response.json())
.then((post) => {
randomFunc(post);
console.log('123');
});
}, [randomFunc]);
const {useState, useEffect} = React;
const Parent = () => {
const [data, setData] = useState([]);
const randomFunc = (dataFromChildComponent) => {
setData(dataFromChildComponent);
};
return <div>
<p>Parent data: {JSON.stringify(data, null,2)}</p>
<p>Child: <Child randomFunc={randomFunc} data={data}/></p>;
</div>
}
const Child = ({randomFunc, data}) => {
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/posts")
.then((response) => response.json())
.then((post) => {
randomFunc(post);
console.log('123');
});
}, [randomFunc]);
return <p>Child data - {JSON.stringify(data, null, 2)}</p>;
}
ReactDOM.render(<Parent />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
(Second code) Does not cause infinite loop:
[Parent.js]
const randomFunc = (dataFromChildComponent) => {
setData(dataFromChildComponent);
};
[Child.js]
useEffect(() => {
randomFunc('Some data!');
console.log('123');
}, [randomFunc]);
const {useState, useEffect} = React;
const Parent = () => {
const [data, setData] = useState([]);
const randomFunc = (dataFromChildComponent) => {
setData(dataFromChildComponent);
};
return <div>
<p>Parent data: {data}</p>
<p>Child: <Child randomFunc={randomFunc} data={data}/></p>
</div>
}
const Child = ({randomFunc, data}) => {
useEffect(() => {
randomFunc('Some data!');
console.log('123');
}, [randomFunc]);
return <p>Child data - {data}</p>
}
ReactDOM.render(<Parent />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
Upvotes: 0
Views: 104
Reputation: 1584
First Program:
As state changes randomFunc
in parent is also evaluated again, thus leading to prop in child component to change and leading to infinite cycle. To stop that from happening you can use https://reactjs.org/docs/hooks-reference.html#usecallback for randomFunc
in parent.js
like below
const randomFunc = useCallback((dataFromChildComponent) => {
setData(dataFromChildComponent);
}, []);
Adding useCallback
will create a memoized version of the function, which won't change till something in the dependency array doesn't change. In this case as there is no dependency, once it is evaluated it won't change again.
Second Program:
Assuming the data
state is null
or undefined
initially. In the case of second program, the useEffect
is called because randomFunc
was initialised once in the beginning. And that would update the parent state data
to Some data!
. This would lead to render cycle getting triggered and evaluating randomFunc
again and thus changing it. This time it would again trigger the useEffect
in child and tries to update the state in parent component. But as the same value Some data!
is sent back to the parent state, the parent state ignores that value, thus ending the cycle of rendering again
Upvotes: 2