Reputation: 1055
The react docs explanation on when the useEffect clean up function is called is confusing and generic to be honest. They even confuse you more by comparing the class mental model with hooks. Class based components work differently from function based components with hooks. React remembers the effect function you provided to useEffect, and runs it after flushing changes to the DOM which is understandable. Now how and when is the function which is returned ("clean up function") called?
Code example below:
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
Upvotes: 3
Views: 1507
Reputation: 24191
Without using the second parameter it will get called on every render.
This is often overkill, so it often a good idea to use the second parameter even if it's empty []
..
eg.
useEffect(() => {....}, []);
Doing the above will only then call the cleanup when the component is physically detached from the DOM.
You can also pass props
instead of []
, this is handy if say a prop change, like what chat room you was in, it would then cleanup the current chat room, and initialize the new chat room etc.
So in your example passing [props.friend.id]
would make sense, because if the id changed, it would make sense to call the cleanup, and then run the effect again for the new id.
Upvotes: 2
Reputation: 112797
The function returned from the function given as first argument to useEffect
will be called when any element in the array given as second argument changes, or on every render if no second argument is given, or when the component is unmounted.
Example
const { useEffect, useState } = React;
function MyComponent({ prop }) {
useEffect(() => {
console.log('Effect!');
return () => console.log('Cleanup!')
}, [prop])
return (
<div>{prop}</div>
);
}
function App() {
const [value, setValue] = useState(0);
useEffect(() => {
setInterval(() => {
setValue(value => value + 1);
}, 1000)
}, [])
return value < 3 ? <MyComponent prop={value} /> : null;
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Upvotes: 6