Easy to understand React Hook recipes by Gabe Ragland
What's all this about?

Hooks are a new addition in React that lets you use state and other React features without writing a class. This website provides easy to understand code examples to help you learn how hooks work and inspire you to take advantage of them in your next project. You may also like my React app builder ✨️

📩  Get new recipes in your inbox
Join 5,145 subscribers. No spam ever.


It's generally a good practice to indicate to users the status of any async request. An example would be fetching data from an API and displaying a loading indicator before rendering the results. Another example would be a form where you want to disable the submit button when the submission is pending and then display either a success or error message when it completes.

Rather then litter your components with a bunch of useState calls to keep track of the state of an async function, you can use our custom hook which takes an async function as an input and returns the pending, value, and error values we need to properly update our UI. As you'll see in the code below, our hook allows both immediate execution and delayed execution using the returned execute function.

import React, { useState, useEffect, useCallback } from 'react';

// Usage
function App() {
  const { execute, pending, value, error } = useAsync(myFunction, false);

  return (
      {value && <div>{value}</div>}
      {error && <div>{error}</div>}
      <button onClick={execute} disabled={pending}>
        {!pending ? 'Click me' : 'Loading...'}

// An async function for testing our hook.
// Will be successful 50% of the time.
const myFunction = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const rnd = Math.random() * 10;
      rnd <= 5
        ? resolve('Submitted successfully 🙌')
        : reject('Oh no there was an error 😞');
    }, 2000);

// Hook
const useAsync = (asyncFunction, immediate = true) => {
  const [pending, setPending] = useState(false);
  const [value, setValue] = useState(null);
  const [error, setError] = useState(null);

  // The execute function wraps asyncFunction and
  // handles setting state for pending, value, and error.
  // useCallback ensures the below useEffect is not called
  // on every render, but only if asyncFunction changes.
  const execute = useCallback(() => {
    return asyncFunction()
      .then(response => setValue(response))
      .catch(error => setError(error))
      .finally(() => setPending(false));
  }, [asyncFunction]);

  // Call execute if we want to fire it right away.
  // Otherwise execute can be called later, such as
  // in an onClick handler.
  useEffect(() => {
    if (immediate) {
  }, [execute, immediate]);

  return { execute, pending, value, error };
  • useSubmit - Original hook by Murat Catal that inspired this recipe
  • SWR - A React Hooks library for remote data fetching. Similar concept, but includes caching, automatic refetching, and many other nifty features.
  • react-async - React component and hook for declarative promise resolution and data fetching.
Next recipe: