React Hooks were definitely a game changer when they got introduced in React v16.8.0. It took me some time to familiarize myself with their usage. But now that I have used them a lot, I can see how using them make React components easier to reason about and maintain.
By creating custom hooks that you reuse within components, you can break up complex logic to smaller understandable functions.
After developing many applications, I have gathered a library of React hook patterns used in almost any of these projects.
One of them is retrieving the previous value of the state for example. Written within a handful lines of code, it makes clever use of the useRef()
hook. As I found out that not only you can use this hook to store the reference to a HTML element, but that it stores any value you pass it.
When combined with the useEffect()
hook, you can create a small helper to store and retrieve the previous value of the variable you passed to it.
Let me show you the usePrevious()
hook.
import React from 'react';
export default function usePrevious<T>(value: T): T {
// Create a reference to hold the previous version of the value,
// as it is basically a generic object whose `current` property can hold any value.
const ref = React.useRef<T>();
// Use the `useEffect` hook to run a callback...
React.useEffect(() => {
// ...to store the passed value on the ref's current property...
ref.current = value;
}, [value]); // ...whenever the value changes.
// And return the currently stored value,
// as this will run before the `useEffect` callback runs.
return ref.current;
}
What to do with this hook?
When you combine the usePrevious
hook with useState
, you can run a callback whenever a value differs from the previous render cycle. I mainly use it in applications to compare boolean variables to their previous values, like the following.
import React from 'react';
const Application = () => {
// Call some external API through a custom hook.
const { data, loading } = useAsyncApi()
// Pass its loading indicator to our created hook.
const wasLoading = usePrevious<boolean>(loading);
// Use the `useEffect` hook to run a callback...
React.useEffect(() => {
// ...to check if the API was loading but now it is completed...
if (!loading && wasLoading) {
// ...and run some arbitary code...
}
}, [loading, wasLoading]); // ...whenever one of these changes.
return (
<div>
{/* ... */}
</div>
);
}
How will you use this hook in your applications? Let me know, as I am curious to find out any other use case you can come up with!
Top comments (2)
The fact that
useEffect
is called after render (return) doesn't mean anything to yourApplication
component, I hope you realise this. Any component update, apart fromloading
, will updatewasLoading
value. And then whenloading
will eventually change, the fact thatuseEffect
is called after render will play cruel joke with you, because yourif
statement will never fire. Hmm......though I guess in this will still work based on the fact that
useEffect
in custom hook will always be invoked before the one inApplication
, just in time switching values back. OK