import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
React Effects are normally triggered by React after each RENDER of the component.
An effect can contain also a cleanup method by returning it from the callback function like this
useEffect(() => {
AppAPI.subscribeToNameChange(nameChanged);
document.title = "name is ${name}"
return () => {
AppAPI.unsubscribeToNameChange(nameChanged);
}
});
Multiple hooks can be used to separate concerns:
function FriendStatusWithCounter(props) {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
// ...
}
useEffect lifecycle
An important thing to note is the effect callbacks are applied at both lifecycles of init/destroy and after each render.
It is helpful because each state change should produce a consistent refresh of the component's UI.
This feature is provided out of the box, while for class based React components this needs to be addressed manually via componentDidUpdate.
Also any listeners bound during the effect's execution are likely to be linked to the current state of the component. So if the state changes, these listeners should be rebound:
function FriendStatus(props) {
// ...
useEffect(() => {
// ...
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
However this is prone to performance issues if the callback execution is expensive.
To help with that, React provides a dirty check feature, by providing an extra param to useEffect:
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
}, [props.friend.id]); // Only re-subscribe if props.friend.id changes
Top comments (0)