Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React useEffect with property as dependency makes infinite loop

I have a component:

const MyComp : React.FC<{ editing?: Data }> = ({editing = { title = '', description = '', date: new Date() } }) => {
    const [data, setData] = useState<Data>({...editing})
    useEffect(() => setData({...editing}), [editing])
    return (/* use data inside here to render component */)
}

The problem is that the useEffect is looping, so React is detecting that the editing prop is changing every, the thing is that i use MyComp without any props like this:

<MyComp></MyComp>

This is really confusing me, i'm kinda lost now on how React works, any ideas on why is this happening?

like image 356
Paulo Marcio Avatar asked Mar 14 '26 05:03

Paulo Marcio


2 Answers

Because editing is an object. Objects are compared by reference. If you don't pass the prop editing to the component, in each render, editing will receive a new link in memory, because you passing a default value to it. So useEffect will assume that dependencies have changed.

You can set primitive types to dependencies.

const MyComp : React.FC<{ editing?: Data }> = ({editing = { title = '', description = '', date: new Date() } }) => {
    const [data, setData] = useState<Data>({...editing})
    useEffect(() => setData({...editing}), [editing.title, editing.description, editing.date.getTime()])
    return (/* use data inside here to render component */)
}
like image 57
Alexander Avatar answered Mar 15 '26 19:03

Alexander


It happens because useEffect uses shallow comparison. You can either destructure the object

const {param1, param2} = editing;
useEffect(() => {
//logic goes here
}, [param1, param2]);

Or write a custom hook that uses Lodash isEqual for example

like image 35
bapafes482 Avatar answered Mar 15 '26 19:03

bapafes482