The Definitive Guide to Making API Calls in React

Knowing how to handle API calls in a web application is a critical skill. There are many different libraries that can help you with this process, but sometimes they are not very beginner friendly.

When using vanilla JavaScript, you might use a library such as Fetch or Axios to make API requests. You can use them in React too, the challenge is how to organize the code around these libraries to make it as readable, scalable and decoupled as possible.

This is not a very intuitive task. It's very common for a new developer just starting out with React to make an API request like this:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// ❌ Don't do this</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">UsersList</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">users</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setUsers</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">([]);</span>

  <span style="color:var(--syntax-name-color)">useEffect</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/users</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setUsers</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">users</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-text-color)">[]);</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">users</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">user</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">(</span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">li</span><span style="color:var(--syntax-text-color)">></span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">user</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">name</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">li</span><span style="color:var(--syntax-text-color)">></span>
      ))}
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
  );
};
</code></span></span>

The above approach works, and is common even in business-level codebases. But using it has some disadvantages:

  • Data is stored in local state
    • Every API call in other components requires a new localuseState
  • Directly call the request library (Fetch) in the component
    • For example, if you change the library to Axios, every component needs to be refactored
    • The same applies to the endpoint, if it changes you need to refactor it in many places
  • Make server-level requests in presentational components
    • Components are designed to render data, not handle fetching logic
    • It is good practice to have a single responsibility for each component, class and function
  • It's not clear what the request will return
    • You rely on the endpoint name to know what the API will return

There are many different ways to solve these problems. Today, I'm going to show you my idea and method to create a reliable and scalable folder and file structure, you can even apply it or the idea behind it on frameworks like Next.js.

Scenario for our example

To understand and combine all the concepts, let's build a Grocery List application step by step. The application will have the following functions:

  • list existing projects;
  • Add new items;
  • remove items;
  • mark the project as completed;

For styling, I'm going to use TailwindCSS . To simulate API requests, we will use Mirage JS, a very easy-to-use and useful API mocking library. To call this API, we will use Fetch .

All examples are on my GitHub , so feel free to clone the repository and play around with it. Details on how to run it are described in the README file.

The end result will look like this:

Create an API endpoint

This application will require 4 API endpoints:

  1. GET /api/grocery-list- Retrieve all items
  2. POST /api/grocery-list- create a new project
  3. PUT /api/grocery-list/:id/done- Mark items with id equal to :id as done
  4. DELETE /api/grocery-list/:id- delete items with id equal to :id

The following example is the most basic case of calling the API. It's not the best, but we'll refactor the code as we go, so you'll understand all the concepts better. Also, we don't focus on the presentation layer, i.e. the actual JSX of the component. It can certainly be improved, but that's not the focus of this article.

1. Retrieve all items

A good place to add the first call is on useEffectthe component, and add a refreshstate as a parameter, so every time this state changes, we'll refetch the item:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/App.jsx</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">App</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">([]);</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refetch</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setRefetch</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span>

  <span style="color:var(--syntax-name-color)">useEffect</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/api/grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">)</span>
      <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">json</span><span style="color:var(--syntax-text-color)">())</span>
      <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
        <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">);</span>
      <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">]);</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">(</span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">li</span> <span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">li</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)">))</span><span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

2. Create a new project

When the user enters an item title and clicks the "Add" button, the application should call the API to create a new item, then fetch all items again to display the new item:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/App.jsx</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">App</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setTitle</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useEffect</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">""</span><span style="color:var(--syntax-text-color)">);</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleAdd</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">preventDefault</span><span style="color:var(--syntax-text-color)">();</span>

    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/api/grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">POST</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
      <span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">JSON</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">stringify</span><span style="color:var(--syntax-text-color)">({</span> <span style="color:var(--syntax-name-color)">title</span> <span style="color:var(--syntax-text-color)">}),</span>
    <span style="color:var(--syntax-text-color)">}).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setTitle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">""</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Empty the title input</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Force refetch to update the list</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-comment-color)">// ...</span>

    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">form</span> <span style="color:var(--syntax-name-color)">onSubmit</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">handleAdd</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">input</span>
        <span style="color:var(--syntax-name-color)">required</span>
        <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"text"</span>
        <span style="color:var(--syntax-name-color)">onChange</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">setTitle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">target</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">value</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span>
        <span style="color:var(--syntax-name-color)">value</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span>
      <span style="color:var(--syntax-text-color)">/></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">button</span> <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"submit"</span><span style="color:var(--syntax-text-color)">></span>Add<span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">button</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">form</span><span style="color:var(--syntax-text-color)">></span>

    <span style="color:var(--syntax-comment-color)">// ...</span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

3. Mark the project as complete

When the user clicks the checkbox to mark the item as complete, the application should dispatch a PUT request, item.idpassing it as a parameter on the endpoint. If the item is already marked complete, we don't need to make a request.

This is very similar to creating a new project, only the request method has changed:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/App.jsx</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">App</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleMarkAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">}</span>

    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`/api/grocery-list/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/done`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">PUT</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
    <span style="color:var(--syntax-text-color)">}).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Force refetch to update the list</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-comment-color)">// ...</span>

    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">(</span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">li</span> <span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>
            <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-comment-color)">/* Checkbox to mark the item as done */</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">input</span>
              <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"checkbox"</span>
              <span style="color:var(--syntax-name-color)">checked</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-string-color)">}</span>
              <span style="color:var(--syntax-name-color)">onChange</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">handleMarkAsDone</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-text-color)">/></span>
            <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span>
          <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">li</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)">))</span><span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>

    <span style="color:var(--syntax-comment-color)">// ...</span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

4. Delete items

This is pretty much the same as we did when we marked the item as complete, but using the DELETE method. When the "Delete" button is clicked, the application should call a function to dispatch the API call:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/App.jsx</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">App</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleDelete</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`/api/grocery-list/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">DELETE</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
    <span style="color:var(--syntax-text-color)">}).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Force refetch to update the list</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-comment-color)">// ...</span>

    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">(</span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">li</span> <span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>
            <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-comment-color)">/* Checkbox to mark the item as done */</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">input</span> <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"checkbox"</span> <span style="color:var(--syntax-name-color)">onChange</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">handleMarkAsDone</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-text-color)">/></span>
            <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span>
          <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>

          <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-comment-color)">/* Delete button */</span><span style="color:var(--syntax-string-color)">}</span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">button</span> <span style="color:var(--syntax-name-color)">onClick</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">handleDelete</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>Delete<span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">button</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">li</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)">))</span><span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>

    <span style="color:var(--syntax-comment-color)">// ...</span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

Final code for the first part of the example

The final code should look like this:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/App.jsx</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">App</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">([]);</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setTitle</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">""</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span>

  <span style="color:var(--syntax-comment-color)">// Retrieve all the items</span>
  <span style="color:var(--syntax-name-color)">useEffect</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/api/grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">)</span>
      <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">json</span><span style="color:var(--syntax-text-color)">())</span>
      <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(({</span> <span style="color:var(--syntax-name-color)">items</span> <span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">));</span>
  <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">]);</span>

  <span style="color:var(--syntax-comment-color)">// Adds a new item</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleAdd</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">preventDefault</span><span style="color:var(--syntax-text-color)">();</span>

    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/api/grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">POST</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
      <span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">JSON</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">stringify</span><span style="color:var(--syntax-text-color)">({</span> <span style="color:var(--syntax-name-color)">title</span> <span style="color:var(--syntax-text-color)">}),</span>
    <span style="color:var(--syntax-text-color)">}).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span>
      <span style="color:var(--syntax-name-color)">setTitle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">""</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-comment-color)">// Mark an item as done</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleMarkAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">}</span>

    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`/api/grocery-list/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/done`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">PUT</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
    <span style="color:var(--syntax-text-color)">}).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-comment-color)">// Deletes an item</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleDelete</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`/api/grocery-list/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">DELETE</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
    <span style="color:var(--syntax-text-color)">}).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">form</span> <span style="color:var(--syntax-name-color)">onSubmit</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">handleAdd</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">input</span>
          <span style="color:var(--syntax-name-color)">required</span>
          <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"text"</span>
          <span style="color:var(--syntax-name-color)">onChange</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">setTitle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">target</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">value</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span>
          <span style="color:var(--syntax-name-color)">value</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span>
        <span style="color:var(--syntax-text-color)">/></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">button</span> <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"submit"</span><span style="color:var(--syntax-text-color)">></span>Add<span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">button</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">form</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">(</span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">li</span> <span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>
              <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">input</span>
                <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"checkbox"</span>
                <span style="color:var(--syntax-name-color)">checked</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-string-color)">}</span>
                <span style="color:var(--syntax-name-color)">onChange</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">handleMarkAsDone</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span>
              <span style="color:var(--syntax-text-color)">/></span>
              <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">button</span> <span style="color:var(--syntax-name-color)">onClick</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">handleDelete</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>delete<span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">button</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">li</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)">))</span><span style="color:var(--syntax-string-color)">}</span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"></></span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

First Refactoring: Creating a Service

Now that we're all set and working, let's refactor the code.

To make the code better, the first thing we can do is create a service for the API calls. Services are basically JavaScript functions responsible for calling the API.

This is useful because if you need to call the API elsewhere, you can just call the service instead of copy-pasting the entire fetchcall.

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/services/grocery-list.js</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">basePath</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/api/grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">getItems</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">basePath</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">json</span><span style="color:var(--syntax-text-color)">());</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">createItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span>
  <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">basePath</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">POST</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
    <span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">JSON</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">stringify</span><span style="color:var(--syntax-text-color)">({</span> <span style="color:var(--syntax-name-color)">title</span> <span style="color:var(--syntax-text-color)">}),</span>
  <span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">itemId</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span>
  <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">basePath</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">itemId</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/done`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">PUT</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">deleteItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">itemId</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span>
  <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">basePath</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">itemId</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">DELETE</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-text-color)">});</span>
</code></span></span>

Note that the service is returning a Promise and all state calls have been removed. We also replaced the repeated base paths of the API endpoints with constants.

Now let's fetchreplace the old call on the component with the new service:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/App.jsx</span>

<span style="color:var(--syntax-comment-color)">// Importing the services</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">createItem</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">deleteItem</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">getItems</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">markItemAsDone</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./services/grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">App</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>

  <span style="color:var(--syntax-name-color)">useEffect</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-comment-color)">// Service call</span>
    <span style="color:var(--syntax-name-color)">getItems</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(({</span> <span style="color:var(--syntax-name-color)">items</span> <span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">]);</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleAdd</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">preventDefault</span><span style="color:var(--syntax-text-color)">();</span>

    <span style="color:var(--syntax-comment-color)">// Service call</span>
    <span style="color:var(--syntax-name-color)">createItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span>
      <span style="color:var(--syntax-name-color)">setTitle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">""</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleMarkAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">}</span>
    <span style="color:var(--syntax-comment-color)">// Service call</span>
    <span style="color:var(--syntax-name-color)">markItemAsDone</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleDelete</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-comment-color)">// Service call</span>
    <span style="color:var(--syntax-name-color)">deleteItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-comment-color)">// ...</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

This is more readable and testable. You can test each service individually instead of testing the components as a whole. Also, it's easier to understand what the code is supposed to do, for example:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// Get the items, then set the items.</span>
<span style="color:var(--syntax-name-color)">getItems</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(({</span> <span style="color:var(--syntax-name-color)">items</span> <span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">});</span>
</code></span></span>

Second Refactoring: Abstracting HTTP Calls

The grocery-listservice relies heavily on the Fetch library. If we decide to change it to Axios, all calls should change. Also, the service layer doesn't need to know how to call the API, only which API it should call.

To avoid confusing these responsibilities, I like to create an API adapter. The name doesn't really matter— the goal here is to configure the API's HTTP calls in one place.

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/adapters/api.js</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">basePath</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">/api</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">api</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">get</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">endpoint</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">basePath</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">endpoint</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">),</span>
  <span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">endpoint</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span>
    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">basePath</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">endpoint</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">POST</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
      <span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">body</span> <span style="color:var(--syntax-error-color)">&&</span> <span style="color:var(--syntax-name-color)">JSON</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">stringify</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">),</span>
    <span style="color:var(--syntax-text-color)">}),</span>
  <span style="color:var(--syntax-name-color)">put</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">endpoint</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span>
    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">basePath</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">endpoint</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">PUT</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
      <span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">body</span> <span style="color:var(--syntax-error-color)">&&</span> <span style="color:var(--syntax-name-color)">JSON</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">stringify</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">body</span><span style="color:var(--syntax-text-color)">),</span>
    <span style="color:var(--syntax-text-color)">}),</span>
  <span style="color:var(--syntax-name-color)">delete</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">endpoint</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span>
    <span style="color:var(--syntax-name-color)">fetch</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">basePath</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">endpoint</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">method</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">DELETE</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">,</span>
    <span style="color:var(--syntax-text-color)">}),</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">api</span> <span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

This is the only file in the entire application that handles HTTP calls. Other files that need to call the API only need to call these methods.

Now, if you decide to replace Fetch with Axios, you only need to change this file.

In terms of testing, it is now possible to test each API method individually without relying on service calls.

Speaking of services, let's fetchreplace the old calls with new ones api..

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/services/grocery-list</span>

<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">api</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">../adapters/api</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">resource</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">getItems</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">api</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">get</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">resource</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">json</span><span style="color:var(--syntax-text-color)">());</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">createItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">api</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">resource</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">title</span> <span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">itemId</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">api</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">put</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">resource</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">itemId</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/done`</span><span style="color:var(--syntax-text-color)">);</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">deleteItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">itemId</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">api</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">delete</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">resource</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">/</span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">itemId</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-text-color)">);</span>
</code></span></span>

Wow, so much cleaner! Note that some responsibilities at the request level no longer exist, such as converting JSON objects to strings. This is not the service's responsibility, now the API layer is doing it.

Likewise, code becomes more readable and testable.

The third refactoring: creating hooks

Now that we have the service and API layers ready, let's improve the presentation layer, the UI components.

These components are currently calling services directly. This works fine, but maintaining state and calling services is more of a function of the application than the responsibility of every component that needs to call the API.

The first hook we're going to create is useGetGroceryListItems()one that contains getItems()API calls.

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/hooks/grocery-list.js</span>

<span style="color:var(--syntax-comment-color)">// Default module import</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-error-color)">*</span> <span style="color:var(--syntax-declaration-color)">as</span> <span style="color:var(--syntax-name-color)">groceryListService</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">../services/grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useGetGroceryListItems</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">([]);</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span>

  <span style="color:var(--syntax-name-color)">useEffect</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">groceryListService</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">getItems</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(({</span> <span style="color:var(--syntax-name-color)">items</span> <span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">);</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">]);</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">refreshItems</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">refreshItems</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

Note that we basically copied the previous behavior of the component into the new hook. We also need to create refreshItems()so we can update the data when needed without directly calling the service again.

We also imported the service module to use it groceryListService.getItems()as, not just call getItems(). This is because our hooks will have similar function names, so to avoid conflicts and improve readability, the entire service module is imported.

Now let's create the rest of the hooks for the other functions (create, update and delete).

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/hooks/grocery-list.js</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useCreateGroceryListItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">createItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">groceryListService</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">createItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">);</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">createItem</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useMarkGroceryListItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">}</span>
    <span style="color:var(--syntax-name-color)">groceryListService</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">markItemAsDone</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useDeleteGroceryListItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">deleteItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">groceryListService</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">deleteItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">);</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">deleteItem</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

Then we need to replace the service call with a hook in the component.

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/App.jsx</span>

<span style="color:var(--syntax-comment-color)">// Hooks import</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">useGetGroceryListItems</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">useCreateGroceryListItem</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">useMarkGroceryListItemAsDone</span><span style="color:var(--syntax-text-color)">,</span>
  <span style="color:var(--syntax-name-color)">useDeleteGroceryListItem</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-string-color)">./hooks/grocery-list</span><span style="color:var(--syntax-string-color)">"</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">App</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">refreshItems</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useGetGroceryListItems</span><span style="color:var(--syntax-text-color)">();</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">createItem</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useCreateGroceryListItem</span><span style="color:var(--syntax-text-color)">();</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useMarkGroceryListItemAsDone</span><span style="color:var(--syntax-text-color)">();</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">deleteItem</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useDeleteGroceryListItem</span><span style="color:var(--syntax-text-color)">();</span>

  <span style="color:var(--syntax-comment-color)">// ...</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleMarkAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-comment-color)">// Validation moved to hook and passing `item` instead of `item.id`</span>
    <span style="color:var(--syntax-name-color)">markItemAsDone</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">refreshItems</span><span style="color:var(--syntax-text-color)">());</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">handleDelete</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-comment-color)">// Passing `item` instead of `item.id`</span>
    <span style="color:var(--syntax-name-color)">deleteItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">refreshItems</span><span style="color:var(--syntax-text-color)">());</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-comment-color)">// ...</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

That's it. Now the application is utilizing the hook, which is useful because if you need to use the same functionality in other components, you can just call it.

If you use a state management solution such as Redux, Context API, or Zustand, you can make state modifications inside hooks instead of calling them at the component level. This helps to make things clearer and the responsibilities are well demarcated.

Final refactor: add loading state

Our application works fine, but there is no feedback to the user during the waiting period for API requests and responses. One solution is to add a loading status to each hook to inform the actual API request status.

After adding the loading state for each hook, the file will look like this:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/hooks/grocery-list.js</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useGetGroceryListItems</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Creating loading state</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">([]);</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span>

  <span style="color:var(--syntax-name-color)">useEffect</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Adding loading state</span>
    <span style="color:var(--syntax-name-color)">groceryListService</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">getItems</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(({</span> <span style="color:var(--syntax-name-color)">items</span> <span style="color:var(--syntax-text-color)">})</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setItems</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">);</span>
      <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Removing loading state</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">]);</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">refreshItems</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">setRefresh</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">refresh</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">refreshItems</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">isLoading</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useCreateGroceryListItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Creating loading state</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">createItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Adding loading state</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">groceryListService</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">createItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Removing loading state</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">createItem</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">isLoading</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useMarkGroceryListItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Creating loading state</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">}</span>

    <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Adding loading state</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">groceryListService</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">markItemAsDone</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Removing loading state</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">isLoading</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-text-color)">};</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useDeleteGroceryListItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useState</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Creating loading state</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">deleteItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Adding loading state</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">groceryListService</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">deleteItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">then</span><span style="color:var(--syntax-text-color)">(()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-name-color)">setIsLoading</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">false</span><span style="color:var(--syntax-text-color)">);</span> <span style="color:var(--syntax-comment-color)">// Removing loading state</span>
    <span style="color:var(--syntax-text-color)">});</span>
  <span style="color:var(--syntax-text-color)">};</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">deleteItem</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">isLoading</span> <span style="color:var(--syntax-text-color)">};</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

Now we need to insert the page's loading state into each hook:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/App.jsx</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">App</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>

  <span style="color:var(--syntax-comment-color)">// Getting loading states and renaming to avoid conflicts</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">refreshItems</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">isFetchingItems</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useGetGroceryListItems</span><span style="color:var(--syntax-text-color)">();</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">createItem</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">isCreatingItem</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useCreateGroceryListItem</span><span style="color:var(--syntax-text-color)">();</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">isUpdatingItem</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useMarkGroceryListItemAsDone</span><span style="color:var(--syntax-text-color)">();</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">deleteItem</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">isDeletingItem</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">useDeleteGroceryListItem</span><span style="color:var(--syntax-text-color)">();</span>

  <span style="color:var(--syntax-comment-color)">// Read each loading state and convert them to a component-level value</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">isLoading</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">isFetchingItems</span> <span style="color:var(--syntax-error-color)">||</span> <span style="color:var(--syntax-name-color)">isCreatingItem</span> <span style="color:var(--syntax-error-color)">||</span> <span style="color:var(--syntax-name-color)">isUpdatingItem</span> <span style="color:var(--syntax-error-color)">||</span> <span style="color:var(--syntax-name-color)">isDeletingItem</span><span style="color:var(--syntax-text-color)">;</span>

  <span style="color:var(--syntax-comment-color)">// ...</span>

  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
    <span style="color:var(--syntax-text-color)"><></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">form</span> <span style="color:var(--syntax-name-color)">onSubmit</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">handleAdd</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">input</span>
          <span style="color:var(--syntax-name-color)">required</span>
          <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"text"</span>
          <span style="color:var(--syntax-name-color)">onChange</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">setTitle</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">event</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">target</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">value</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span>
          <span style="color:var(--syntax-name-color)">value</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span>
          <span style="color:var(--syntax-name-color)">disabled</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-comment-color)">/* Loading State */</span><span style="color:var(--syntax-string-color)">}</span>
        <span style="color:var(--syntax-text-color)">/></span>
        <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">button</span> <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"submit"</span> <span style="color:var(--syntax-name-color)">disabled</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span> <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-comment-color)">/* Loading State */</span><span style="color:var(--syntax-string-color)">}</span>
          Add
        <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">button</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">form</span><span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">items</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">((</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">(</span>
          <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">li</span> <span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">id</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>
              <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">input</span>
                <span style="color:var(--syntax-name-color)">type</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"checkbox"</span>
                <span style="color:var(--syntax-name-color)">checked</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-string-color)">}</span>
                <span style="color:var(--syntax-name-color)">onChange</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">handleMarkAsDone</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span>
                <span style="color:var(--syntax-name-color)">disabled</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-comment-color)">/* Loading State */</span><span style="color:var(--syntax-string-color)">}</span>
              <span style="color:var(--syntax-text-color)">/></span>
              <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">label</span><span style="color:var(--syntax-text-color)">></span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">button</span> <span style="color:var(--syntax-name-color)">onClick</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">handleDelete</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-name-color)">disabled</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">isLoading</span><span style="color:var(--syntax-string-color)">}</span><span style="color:var(--syntax-text-color)">></span> <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-comment-color)">/* Loading State */</span><span style="color:var(--syntax-string-color)">}</span>
              delete
            <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">button</span><span style="color:var(--syntax-text-color)">></span>
          <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">li</span><span style="color:var(--syntax-text-color)">></span>
        <span style="color:var(--syntax-text-color)">))</span><span style="color:var(--syntax-string-color)">}</span>
      <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">ul</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"></></span>
  <span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

Bonus Refactoring: Create Utilities

Note that in useMarkGroceryListItemAsDone()the hook we have a logic to determine if the item should be updated:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/hooks/grocery-list.js</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">return</span><span style="color:var(--syntax-text-color)">;</span> <span style="color:var(--syntax-comment-color)">// Don't call the service</span>
  <span style="color:var(--syntax-text-color)">}</span>

  <span style="color:var(--syntax-comment-color)">// Call the service and update the item</span>
</code></span></span>

This is not an ideal place for this logic, as it may be needed elsewhere, forcing it to be repeated, and it's the business logic of the application, not just specific logic for this hook.

One possible solution is to create a util and add this logic there, so we only call the function in the hook:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-comment-color)">// src/utils/grocery-list.js</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">shouldUpdateItem</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">isDone</span><span style="color:var(--syntax-text-color)">;</span>
</code></span></span>

Then call this utility in your hook:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">useMarkGroceryListItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-comment-color)">// ...</span>

  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">markItemAsDone</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-comment-color)">// Calling the util</span>
    <span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">shouldUpdateItem</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">item</span><span style="color:var(--syntax-text-color)">))</span> <span style="color:var(--syntax-text-color)">{</span>
      <span style="color:var(--syntax-declaration-color)">return</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-text-color)">}</span>

    <span style="color:var(--syntax-comment-color)">// ...</span>
</code></span></span>

Now hooks don't depend on any business-related logic: they just call a function and return its value.

wrap up

All refactorings we do are aimed at improving code quality and making it more readable for humans. The code works at first, but is not scalable and not testable. These are very important characteristics of a great codebase.

We basically apply the Single Responsibility Principle to code to make it better. This code can be used as a base for building other services, connecting to external APIs, creating other components, etc.

As mentioned, you can also plug in your state management solution here and manage the global state of your application in the hooks we created.

To further improve your code, it is best to use React Query to take advantage of its caching, refetching, and auto-invalidation features.

That's it! Hope you learned something new today to make your coding journey even better!

 

Guess you like

Origin blog.csdn.net/jascl/article/details/131304126