115 lines
3.5 KiB
Markdown
115 lines
3.5 KiB
Markdown
![]() |
---
|
||
|
tags:
|
||
|
- javascript
|
||
|
- react
|
||
|
---
|
||
|
|
||
|
# `useEffect`
|
||
|
|
||
|
`useEffect` should be used for any background process that does not arise as a
|
||
|
result of a user interaction or standard state change. The canonical example
|
||
|
would be dispatching a request to an API to retrieve data to display in a
|
||
|
component's initial render.
|
||
|
|
||
|
`useEffect` enshrines but also simplifies the
|
||
|
[lifecyle methods](Lifecycle_methods.md) that are used with
|
||
|
class-based React components.
|
||
|
|
||
|
## Demonstration
|
||
|
|
||
|
```jsx
|
||
|
const [workflowTitle, setWorkflowTitle] = useState("");
|
||
|
const [loading, setLoading] = useState(false);
|
||
|
|
||
|
useEffect(() => {
|
||
|
const fetchWorkflowTitle = () => {
|
||
|
axios
|
||
|
.post(`${process.env.REACT_APP_ENDPOINT}/load-workflows`, {
|
||
|
workflow_id: project_id,
|
||
|
user_id: isAuth?.userId,
|
||
|
})
|
||
|
.then((res) => {
|
||
|
setWorkflowTitle(res?.data?.meta.name);
|
||
|
})
|
||
|
.finally(() => setLoading(false))
|
||
|
.catch((err) => {
|
||
|
console.error(err);
|
||
|
});
|
||
|
};
|
||
|
setLoading(true);
|
||
|
fetchWorkflowTitle();
|
||
|
}, [project_id, isAuth]);
|
||
|
```
|
||
|
|
||
|
In this example we fetch some data from a REST API and store the response value
|
||
|
as state, which can then be accessed within our JSX template.
|
||
|
|
||
|
## Function placement
|
||
|
|
||
|
In the example, the function is declared inside of the `useEffect` hook and then
|
||
|
called. We do this to avoid adding the function to the dependency array, which
|
||
|
we couldn't do if we defined it outside of the hook, somewhere in the component.
|
||
|
If we did this, the function would run on every render by default and would be
|
||
|
recalled again because of its placement in the dependency array, which leads to
|
||
|
the 'too many rerenders' error.
|
||
|
|
||
|
An alternative would be to define it outside of the component itself but this is
|
||
|
difficult since it requires state from the component to run.
|
||
|
|
||
|
## Dependency array
|
||
|
|
||
|
Note the array that is the second argument to `useEffect`. This is the
|
||
|
**dependency array** and is how we manage the lifecycle of the side-effect.
|
||
|
|
||
|
- After the initial call on render, the function within the `useEffect` block
|
||
|
will run any time one of the dependencies update. The dependency array
|
||
|
typically refers to variables that are defined within the hook but can also
|
||
|
contain references to variables outside of it.
|
||
|
|
||
|
- If you do not include the array, the effect runs on every render
|
||
|
|
||
|
- If you pass an empty array, the effect will only run once on the initial
|
||
|
render
|
||
|
|
||
|
## Cleanup functions
|
||
|
|
||
|
The syntax of the `useEffect` hook also allows you to handle cleanup: something
|
||
|
you want to do when the component unmounts (another example of how this hook
|
||
|
recasts the traditional [lifecycle methods](Lifecycle_methods.md))
|
||
|
. In addition to running on unmount, the cleanup function will run before the
|
||
|
effect runs again (i.e. when it runs in response to a change in one of the
|
||
|
elements of the dependency araray). This is chiefly used to prevent
|
||
|
[memory leaks](Memory_leaks.md) and the
|
||
|
['update on unmounted component error'](React_errors.md#state-update-on-unmounted-component).
|
||
|
|
||
|
You do this by having a `return` clause after the main effect. Schematically:
|
||
|
|
||
|
```js
|
||
|
useEffect(() => {
|
||
|
// Run your effect;
|
||
|
return () => {
|
||
|
// Put your cleanup function here
|
||
|
};
|
||
|
}, [input]);
|
||
|
```
|
||
|
|
||
|
Here is an example of using a cleanup to cancel a subscription
|
||
|
|
||
|
```js
|
||
|
useEffect(() => {
|
||
|
let isApiSubscribed = true;
|
||
|
axios.get(API).then((response) => {
|
||
|
if (isApiSubscribed) {
|
||
|
// handle success
|
||
|
}
|
||
|
});
|
||
|
return () => {
|
||
|
isApiSubscribed = false;
|
||
|
};
|
||
|
}, []);
|
||
|
```
|
||
|
|
||
|
## Resources
|
||
|
|
||
|
[Understanding the React useEffect cleanup function]()
|