cribbble

React Hooks: useMountedState

avatar
Ward Poel

What does this hook do? It's a more advanced useState hook. When setting a new state, the hook makes sure the component is still mounted.

Usage

Exactly the same as React's useState hook. For this hook, we will use our custom useMountedRef hook.

Example

Let's say we have an API that fetches a person. If we click accidentally on the wrong person, we fetch a person we don't want. But because react renders the Person component, the API request is also fired. Let's say we now go back to our previous screen. The request is still going on, when the request is done we try to set the state, but this component is unmounted so React will throw a warning. You can easily avoid this by using the useMountedState hook. As the setter of this hook will check if the component is still mounted (using my useMountedRef hook)

export default function Person(props) {
	let { id } = props;
	let [person, setPeron] = useMountedState();

	useEffect(() => {
		async function fetchPerson() {
			let response = await fetch('/api/person/' + id);
			let data = await response.json();
			setPeron(data);
		}

		fetchPerson();
	}, [id])

	if (person == undefined) return <div>Loading...</div>

	return <h1>{person.name}</h1>
}

The hook

import { useState, useCallback } from 'react';

import useMountedRef from './use-mounted-ref';

export default function useMountedState(value) {
	let mountedRef = useMountedRef();
	let [state, setState] = useState(value);

	let setMountedState = useCallback(
		(newState) => {
			if (mountedRef.current) {
				setState(newState);
			}
		},
		[mountedRef],
	);

	return [state, setMountedState];
}

If you have any questions, I'm @WardPoel on Twitter.