useEffect
The useEffect
hook serves a the primary way for handling side effects in a Melody component.
It allows you to execute code when,
it is mounted
it is updated
it is unmounted (removed)
Execute a side effect when needed
useEffect(sideEffectFunction, cacheKeyProperties[])
The most common form of useEffect
accepts a function, the side effect you want to execute, and an array of variables it depends on. Those cacheKeyProperties
are used to determine whether to execute the side effect again or not.
// we'll create a reusable data loading hook for items
function useItemData({ itemId }) {
// use an atom to store the data
const [getData, setData, data] = useAtom({});
// this hook will be executed after the component has been mounted
// and it will only be executed again if the itemId changes
useEffect(() => {
// ceremony to get a URL and setup an abortable fetch
const url = getItemDataUrl(itemId);
const controller = new AbortController();
const signal = controller.signal;
fetch(url, { signal }).then(response => {
return response.json();
// finally update the data
}).then(setData);
// this function is executed when
// 1. the component is unmounted or
// 2. the itemId changes
// we'll use it to cancel the request if its still running
return () => controller.abort();
}, [itemId]);
return [ getData, data ];
}
Execute a side effect on mount and unmount
useEffect(sideEffectFunction, [])
When given an empty array the side effect will never be evaluated again, as the cache key never changes. This gives a chance to build a side effect that executes when the component mounts and unmounts.
function useDocumentTitle(title) {
useEffect(() => {
// executed after component was mounted
const oldTitle = document.title;
document.title = title;
// executed when the component is unmounted
return () => document.title = oldTitle;
}, []);
};
Use a side effect on mount, every render and unmount
useEffect(sideEffectFunction)
You can also omit the cacheKeyProperties
array entirely if you want to create a side effect that executed every time the component is rendered.
function useSlowDeviceKiller() {
useEffect(() => {
// executed on component mount and every single render
fibonacci(10);
// this function will be executed on _every render_ before
// the side effect is re-evaluated
return () => fibonacci(7);
});
}
While technically feasible you most likely won't need this variant. It is a performance disaster waiting to happen.
We strongly advise that if you do really need it, you accompany it with some documentation on why you decided to go that route to help your colleagues avoid introducing issues later on.
Last updated
Was this helpful?