Refresh Component Fetchs Data From Store Again

The writer selected Creative Commons to receive a donation equally part of the Write for DOnations program.

Introduction

In React development, spider web application programming interfaces (APIs) are an integral part of single-page application (SPA) designs. APIs are the main way for applications to programmatically communicate with servers to provide users with real-time data and to save user changes. In React applications, you lot will employ APIs to load user preferences, display user information, fetch configuration or security information, and save application land changes.

In this tutorial, you lot'll use the useEffect and useState Hooks to fetch and display information in a sample application, using JSON server as a local API for testing purposes. You'll load information when a component start mounts and save customer inputs with an API. You lot'll also refresh data when a user makes a change and learn how to ignore API requests when a component unmounts. By the end of this tutorial, you'll be able to connect your React applications to a variety of APIs and you'll be able to ship and receive real-fourth dimension data.

Prerequisites

  • You will need a development environment running Node.js; this tutorial was tested on Node.js version 10.22.0 and npm version half dozen.14.half-dozen. To install this on macOS or Ubuntu 18.04, follow the steps in How to Install Node.js and Create a Local Development Surround on macOS or the Installing Using a PPA section of How To Install Node.js on Ubuntu 18.04.

  • A React development surround ready up with Create React App, with the non-essential boilerplate removed. To set this upward, follow Step 1 — Creating an Empty Project of the How To Manage State on React Class Components tutorial. This tutorial will apply api-tutorial equally the project name.

  • You will be using React components and Hooks in this tutorial, including the useState and useEffect Hooks. You tin can learn virtually components and Hooks in our tutorials How To Manage State with Hooks on React Components and How To Handle Async Data Loading, Lazy Loading, and Code Splitting with React.

  • You lot will also demand a bones knowledge of JavaScript and HTML, which you can find in our How To Build a Website with HTML series and in How To Code in JavaScript. Basic knowledge of CSS would also be useful, which you tin find at the Mozilla Developer Network.

Step 1 — Creating a Projection and a Local API

In this step, yous'll create a local REST API using JSON server, which you volition use as a test data source. Later on, y'all'll build an application to display a grocery list and to add items to the list. JSON server will be your local API and will give yous a live URL to make GET and Mail service requests. With a local API, yous have the opportunity to prototype and test components while you or some other squad develops live APIs.

By the cease of this footstep, yous'll be able to create local mock APIs that you can connect to with your React applications.

On many agile teams, front-cease and API teams work on a problem in parallel. In gild to develop a front-end application while a remote API is still in development, you tin create a local version that yous tin can use while waiting for a complete remote API.

There are many ways to brand a mock local API. You tin create a simple server using Node or another language, but the quickest way is to use the JSON server Node packet. This projection creates a local Rest API from a JSON file.

To begin, install json-server:

                      
  1. npm install --salvage-dev json-server

When the installation is finished, you'll receive a success message:

                      

Output

+ json-server@0.16.1 added 108 packages from xl contributors and audited 1723 packages in fourteen.505s 73 packages are looking for funding run `npm fund` for details plant 0 vulnerabilities

json-server creates an API based on a JavaScript object. The keys are the URL paths and the values are returned as a response. You store the JavaScript object locally and commit it to your source command.

Open up a file called db.json in the root of your awarding. This will exist the JSON that stores the data you lot request from the API:

                      
  1. nano db.json

Add an object with the primal of list and an assortment of values with an id and a cardinal of item. This will list the item for the grocery listing. The cardinal listing will somewhen requite yous a URL with an endpoint of /list:

api-tutorial/db.json

                      {            "listing"            :            [            {            "id"            :            1            ,            "item"            :            "bread"            }            ,            {            "id"            :            two            ,            "item"            :            "grapes"            }            ]            }                  

In this snippet, you lot accept difficult-coded bread and grapes as a starting point for your grocery list.

Save and close the file. To run the API server, you will use json-server from the command line with an statement point to the API configuration file. Add it equally a script in your package.json.

Open up package.json:

                      
  1. nano package.json

And so add a script to run the API. In add-on, add together a delay property. This will throttle the response, creating a delay between your API request and the API response. This will give you some insights into how the awarding will carry when waiting for a server response. Add together a delay of 1500 milliseconds. Finally, run the API on port 3333 using the -p option so information technology won't conflict with the create-react-app run script:

api-tutorial/parcel.json

                      {            "name"            :            "practice-14-api"            ,            "version"            :            "0.i.0"            ,            "private"            :            true            ,            "dependencies"            :            {            "@testing-library/jest-dom"            :            "^4.2.four"            ,            "@testing-library/react"            :            "^ix.3.ii"            ,            "@testing-library/user-event"            :            "^vii.i.2"            ,            "react"            :            "^16.13.i"            ,            "react-dom"            :            "^16.xiii.1"            ,            "react-scripts"            :            "3.iv.iii"            }            ,            "scripts"            :            {                          "api"              :              "json-server db.json -p 3333 --delay 1500"              ,                        "start"            :            "react-scripts start"            ,            "build"            :            "react-scripts build"            ,            "test"            :            "react-scripts test"            ,            "eject"            :            "react-scripts eject"            }            ,            "eslintConfig"            :            {            "extends"            :            "react-app"            }            ,            "browserslist"            :            {            "production"            :            [            ">0.2%"            ,            "not dead"            ,            "not op_mini all"            ]            ,            "development"            :            [            "final i chrome version"            ,            "concluding one firefox version"            ,            "last 1 safari version"            ]            }            ,            "devDependencies"            :            {            "json-server"            :            "^0.sixteen.1"            }            }                  

Save and shut the file. In a new last or tab, first the API server with the post-obit command:

                      
  1. npm run api

Keep this running during the residual of the tutorial.

When you run the control, you will receive an output that lists the API resources:

                      

Output

> json-server db.json -p 3333 \{^_^}/ hi! Loading db.json Done Resources http://localhost:3333/list Home http://localhost:3333 Type south + enter at whatever time to create a snapshot of the database

Open http://localhost:3333/list and you'll find the live API:

API results, 1

When you lot open up an endpoint in your browser, you are using the Become method. Just json-server is not limited to the GET method. You lot can perform many other Residual methods as well. For example, you lot tin POST new items. In a new terminal window or tab, use ringlet to POST a new item with a blazon of application/json:

                      
  1. roll -d '{"item":"rice"}' -H 'Content-Type: application/json' -X POST http://localhost:3333/list

Notation that you must stringify the content earlier you lot send information technology. After running the curlicue command, y'all'll receive a success bulletin:

                      

Output

{ "item": "rice", "id": iii }

If you refresh the browser, the new particular volition appear:

Updated content, 2

The POST request volition likewise update the db.json file. Be mindful of the changes, since there are no barriers to accidentally saving unstructured or unhelpful content equally you lot work on your application. Be sure to check whatever changes before committing into version control.

In this step, you created a local API. Y'all learned how to create a static file with default values and how to fetch or update those values using RESTful actions such as Become and POST. In the next step, you'll create services to fetch data from the API and to display in your application.

Step 2 — Fetching Data from an API with useEffect

In this pace, you'll fetch a list of groceries using the useEffect Hook. You'll create a service to consume APIs in carve up directories and phone call that service in your React components. Later on yous call the service, you'll save the data with the useState Claw and display the results in your component.

By the terminate of this footstep, you lot'll be able to call web APIs using the Fetch method and the useEffect Hook. You'll also exist able to salvage and display the results.

At present that y'all have a working API, you demand a service to fetch the data and components to display the information. Start past creating a service. Y'all can fetch data directly within any React component, just your projects volition exist easier to browse and update if you keep your data retrieval functions dissever from your display components. This volition let you to reuse methods across components, mock in tests, and update URLs when endpoints change.

Create a directory chosen services within the src directory:

                      
  1. mkdir src/services

Then open a file called list.js in your text editor:

                      
  1. nano src/services/list.js

You'll utilise this file for any actions on the /list endpoint. Add a function to retrieve the data using the fetch function:

api-tutorial/src/services/list

                      export            function            getList            (            )            {            render            fetch            (            'http://localhost:3333/list'            )            .            then            (            information            =>            data.            json            (            )            )            }                  

The but goal of this function is to access the information and to convert the response into JSON using the data.json() method. Become is the default action, so yous don't demand any other parameters.

In improver to fetch, there are other pop libraries such as Axios that tin give you lot an intuitive interface and will allow you to add default headers or perform other actions on the service. But fetch will work for most requests.

Save and close the file. Side by side, open App.css and add some minimal styling:

                      
  1. nano src/components/App/App.css

Add a form of wrapper with a small amount of padding past replacing the CSS with the following:

api-tutorial/src/components/App/App.css

                      .wrapper            {            padding            :            15px;            }                  

Salvage and shut the file. At present y'all demand to add in code to retrieve the data and display it in your awarding.

Open App.js:

                      
  1. nano src/components/App/App.js

In functional components, y'all use the useEffect Hook to fetch data when the component loads or some data changes. For more information on the useEffect Hook, check out How To Handle Async Information Loading, Lazy Loading, and Lawmaking Splitting with React. Y'all'll also need to save the results with the useState Hook.

Import useEffect and useState, so create a variable chosen list and a setter called setList to hold the data yous fetch from the service using the useState Hook:

api-tutorial/src/components/App/App.js

                      import            React,                          {              useEffect,              useState              }                        from            'react'            ;            import            './App.css'            ;            part            App            (            )            {                          const              [list,              setList]              =              useState              (              [              ]              )              ;                        return            (            <            >            <            /            >            )            }            consign            default            App;                  

Next, import the service, then call the service inside your useEffect Claw. Update the list with setList if the component is mounted. To empathise why you should check if the component is mounted before setting the data, come across Step 2 — Preventing Errors on Unmounted Components in How To Handle Async Data Loading, Lazy Loading, and Code Splitting with React.

Currently you lot are just running the effect once when the page loads, so the dependency array volition be empty. In the adjacent step, you'll trigger the effect based on dissimilar folio actions to ensure that you always have the most up-to-date information.

Add together the following highlighted lawmaking:

api-tutorial/src/components/App/App.js

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;                          import              {              getList              }              from              '../../services/listing'              ;                        role            App            (            )            {            const            [list,            setList]            =            useState            (            [            ]            )            ;                          useEffect              (              (              )              =>              {                                      let              mounted              =              true              ;                                      getList              (              )                                      .              and so              (              items              =>              {                                      if              (mounted)              {                                      setList              (items)                                      }                                      }              )                                      return              (              )              =>              mounted              =              faux              ;                                      }              ,              [              ]              )                        render            (            <            >            <            /            >            )            }            export            default            App;                  

Finally, loop over the items with .map and display them in a list:

api-tutorial/src/components/App/App

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList            }            from            '../../services/list'            ;            function            App            (            )            {            const            [list,            setList]            =            useState            (            [            ]            )            ;            useEffect            (            (            )            =>            {            let            mounted            =            truthful            ;            getList            (            )            .            then            (            items            =>            {            if            (mounted)            {            setList            (items)            }            }            )            return            (            )            =>            mounted            =            false            ;            }            ,            [            ]            )            render                          (                                      <div className=              "wrapper"              >                                      <h1>My Grocery Listing<              /h1>                                      <ul>                                      {list.              map              (              detail              =>              <li central=              {particular.item}              >              {item.item}              <              /li>              )              }                                      <              /ul>                                      <              /div>                                      )                        }            export            default            App;                  

Save and close the file. When you exercise, the browser will refresh and you'll find a list of items:

List Items, 3

In this step, you set up a service to call up data from an API. You learned how to phone call the service using the useEffect Claw and how to prepare the data on the page. You also displayed the data within your JSX.

In the side by side pace, y'all'll submit information to the API using POST and utilize the response to alert your users that an actions was successful.

Footstep three — Sending Data to an API

In this stride, you lot'll send data back to an API using the Fetch API and the Postal service method. Yous'll create a component that will use a spider web form to send the data with the onSubmit upshot handler and will brandish a success bulletin when the action is complete.

By the cease of this step, you'll exist able to send information to an API and you'll be able to alert the user when the request resolves.

Sending Data to a Service

You have an application that volition display a list of grocery items, but information technology'southward not a very useful grocery app unless you can save content equally well. You need to create a service that will Postal service a new detail to the API.

Open up src/services/list.js:

                      
  1. nano src/services/list.js

Within the file, add a function that will take an item as an argument and will ship the data using the POST method to the API. Equally before, you can use the Fetch API. This fourth dimension, you'll demand more than information. Add together an object of options as the second argument. Include the method—POST—along with headers to set the Content-Type to awarding/json. Finally, send the new object in the torso. Be sure to catechumen the object to a string using JSON.stringify.

When yous receive a response, convert the value to JSON:

tutorial/src/services/list.js

                      consign            part            getList            (            )            {            return            fetch            (            'http://localhost:3333/list'            )            .            then            (            information            =>            data.            json            (            )            )            }                          export              function              setItem              (              item              )              {                                      return              fetch              (              'http://localhost:3333/list'              ,              {                                      method              :              'POST'              ,                                      headers              :              {                                      'Content-Type'              :              'awarding/json'                                      }              ,                                      trunk              :              JSON              .              stringify              (              {              detail              }              )                                      }              )                                      .              then              (              data              =>              data.              json              (              )              )                                      }                              

Salvage and close the file.

Note: In production applications, you'll demand to add together fault handling and checking. For example, if y'all misspelled the endpoint, you'd even so receive a 404 response and the information.json() method would return an empty object. To solve the issue, instead of converting the response to JSON, y'all could check the data.ok property. If it is falsy, you could throw an error and so apply the .catch method in your component to display a failure bulletin to the users.

Now that you lot have created a service, you demand to consume the service within your component.

Open App.js:

                      
  1. nano src/components/App/App.js

Add a course element surrounding an input and a submit button:

api-tutorial/src/components/App/App.js

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList            }            from            '../../services/list'            ;            function            App            (            )            {            const            [list,            setList]            =            useState            (            [            ]            )            ;            useEffect            (            (            )            =>            {            let            mounted            =            true            ;            getList            (            )            .            then            (            items            =>            {            if            (mounted)            {            setList            (items)            }            }            )            render            (            )            =>            mounted            =            fake            ;            }            ,            [            ]            )            render            (            <div className=            "wrapper"            >            <h1>My Grocery List<            /h1>            <ul>            {list.            map            (            item            =>            <li key=            {particular.particular}            >            {detail.detail}            <            /li>            )            }            <            /ul>                          <grade>                                      <characterization>                                      <p>New Item<              /p>                                      <input blazon=              "text"              /              >                                      <              /label>                                      <push button type=              "submit"              >Submit<              /button>                                      <              /form>                        <            /div>            )            }            consign            default            App;                  

Be sure to environs the input with a label so that the form is accessible past a screen reader. Information technology's besides a proficient do to add a type="submit" to the push so that it's clear the role is to submit the grade.

Salvage the file. When you do, the browser will refresh and you'll find your form.

Grocery List Form

Next, catechumen the input to a controlled component. You'll demand a controlled component and so that you can articulate the field after the user successfully submits a new list item.

First, create a new land handler to hold and ready the input information using the useState Hook:

api-tutorial/src/components/App/App.js

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList            }            from            '../../services/list'            ;            function            App            (            )            {                          const              [itemInput,              setItemInput]              =              useState              (              ''              )              ;                        const            [list,            setList]            =            useState            (            [            ]            )            ;            useEffect            (            (            )            =>            {            let            mounted            =            true            ;            getList            (            )            .            and then            (            items            =>            {            if            (mounted)            {            setList            (items)            }            }            )            return            (            )            =>            mounted            =            false            ;            }            ,            [            ]            )            return            (            <div className=            "wrapper"            >            <h1>My Grocery List<            /h1>            <ul>            {list.            map            (            item            =>            <li key=            {item.item}            >            {item.item}            <            /li>            )            }            <            /ul>            <grade>            <label>            <p>New Item<            /p>            <input blazon=            "text"            onChange=              {              event              =>              setItemInput              (event.target.value)              }              value=              {itemInput}                        /            >            <            /characterization>            <button blazon=            "submit"            >Submit<            /push>            <            /form>            <            /div>            )            }            export            default            App;                  

After creating the state handlers, set the value of the input to itemInput and update the value past passing the effect.target.value to the setItemInput function using the onChange event handler.

Now your users tin can fill out a course with new listing items. Adjacent you will connect the grade to your service.

Create a office called handleSubmit. handleSubmit will take an event as an argument and will telephone call event.preventDefault() to end the form from refreshing the browser.

Import setItem from the service, then telephone call setItem with the itemInput value inside the handleSubmit function. Connect handleSubmit to the class by passing it to the onSubmit issue handler:

api-tutorial/src/components/App/App.js

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList              ,              setItem            }            from            '../../services/list'            ;            function            App            (            )            {            const            [itemInput,            setItemInput]            =            useState            (            ''            )            ;            const            [list,            setList]            =            useState            (            [            ]            )            ;            useEffect            (            (            )            =>            {            allow            mounted            =            true            ;            getList            (            )            .            so            (            items            =>            {            if            (mounted)            {            setList            (items)            }            }            )            return            (            )            =>            mounted            =            false            ;            }            ,            [            ]            )                          const              handleSubmit              =              (              e              )              =>              {                        east.              preventDefault              (              )              ;                                      setItem              (itemInput)                                      }              ;                        return            (            <div className=            "wrapper"            >            <h1>My Grocery Listing<            /h1>            <ul>            {list.            map            (            detail            =>            <li key=            {particular.item}            >            {item.item}            <            /li>            )            }            <            /ul>            <form            onSubmit=              {handleSubmit}                        >            <label>            <p>New Item<            /p>            <input type=            "text"            onChange=            {            outcome            =>            setItemInput            (event.target.value)            }            value=            {itemInput}            /            >            <            /label>            <push type=            "submit"            >Submit<            /push>            <            /form>            <            /div>            )            }            consign            default            App;                  

Salvage the file. When you practise, you lot'll be able to submit values. Detect that you'll receive a successful response in the network tab. But the list doesn't update and the input doesn't clear.

Submit successful, 5

Showing a Success Message

It'south always a expert practise to give the user some indication that their action was successful. Otherwise a user may try and resubmit a value multiple times or may think their activity failed and volition leave the application.

To practice this, create a stateful variable and setter function with useState to point whether to show a user an alert message. If warning is true, brandish an <h2> tag with the message Submit Successful.

When the setItem promise resolves, clear the input and prepare the alarm bulletin:

api-tutorial/src/components/App/App.js

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList,            setItem            }            from            '../../services/listing'            ;            function            App            (            )            {                          const              [alert,              setAlert]              =              useState              (              simulated              )              ;                        const            [itemInput,            setItemInput]            =            useState            (            ''            )            ;            const            [list,            setList]            =            useState            (            [            ]            )            ;            useEffect            (            (            )            =>            {            let            mounted            =            truthful            ;            getList            (            )            .            then            (            items            =>            {            if            (mounted)            {            setList            (items)            }            }            )            return            (            )            =>            mounted            =            imitation            ;            }            ,            [            ]            )            const            handleSubmit            =            (            e            )            =>            {            eastward.            preventDefault            (            )            ;            setItem            (itemInput)                          .              so              (              (              )              =>              {                                      setItemInput              (              ''              )              ;                                      setAlert              (              true              )              ;                                      }              )                        }            ;            render            (            <div className=            "wrapper"            >            <h1>My Grocery Listing<            /h1>            <ul>            {listing.            map            (            item            =>            <li key=            {item.detail}            >            {detail.item}            <            /li>            )            }            <            /ul>                          {alarm              &&              <h2>              Submit Successful<              /h2>              }                        <form onSubmit=            {handleSubmit}            >            <label>            <p>New Detail<            /p>            <input blazon=            "text"            onChange=            {            effect            =>            setItemInput            (event.target.value)            }            value=            {itemInput}            /            >            <            /characterization>            <button type=            "submit"            >Submit<            /button>            <            /grade>            <            /div>            )            }            export            default            App;                  

Save the file. When you practice, the page will refresh and y'all'll see a success message later on the API request resolves.

Submit and message, 6

There are many other optimizations you can add. For example, y'all may want to disable class inputs while there is an active asking. You tin can learn more virtually disabling form elements in How To Build Forms in React.

Now you have alerted a user that the event was successful, but the warning message doesn't become abroad and the list doesn't update. To fix this, get-go by hiding the warning. In this case, you lot'd want to hide the information after a cursory period, such equally one second. You tin can apply the setTimeout part to phone call setAlert(false), but you lot'll demand to wrap information technology in useEffect to ensure that it does not run on every component render.

Within of App.js create a new result and pass the alert to the array of triggers. This will cause the effect to run whatsoever time alert changes. Notice that this will run if alert changes from imitation to truthful, but information technology volition besides run when alert changes from true to fake. Since you only want to hibernate the alarm if information technology is displayed, add a status within the outcome to only run setTimeout if warning is true:

api-tutorial/src/components/App/App.js

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList,            setItem            }            from            '../../services/list'            ;            function            App            (            )            {            const            [alert,            setAlert]            =            useState            (            false            )            ;            const            [itemInput,            setItemInput]            =            useState            (            ''            )            ;            const            [listing,            setList]            =            useState            (            [            ]            )            ;            ...                          useEffect              (              (              )              =>              {                                      if              (alert)              {                                      setTimeout              (              (              )              =>              {                                      setAlert              (              false              )              ;                                      }              ,              thousand              )                                      }                                      }              ,              [alert]              )                        const            handleSubmit            =            (            e            )            =>            {            due east.            preventDefault            (            )            ;            setItem            (itemInput)            .            and then            (            (            )            =>            {            setItemInput            (            ''            )            ;            setAlert            (            true            )            ;            }            )            }            ;            render            (            <div className=            "wrapper"            >            ...            <            /div>            )            }            export            default            App;                  

Run the setTimeout function subsequently yard milliseconds to ensure the user has fourth dimension to read the change.

Save the file. At present you lot take an effect that will run whenever alert changes. If there is an active alert, it will start a timeout office that will shut the warning after one 2d.

Hide alert, 7

Refreshing Fetched Data

Now you need a way to refresh the stale list of data. To do this, you lot tin can add together a new trigger to the useEffect Hook to rerun the getList asking. To ensure yous have the well-nigh relevant data, you need a trigger that will update anytime there is a change to the remote data. Fortunately, you lot tin reuse the alert country to trigger another data refresh since you know it will run whatsoever fourth dimension a user updates the data. As before, you lot accept to plan for the fact that the outcome will run every fourth dimension alert changes including when the alert message disappears.

This time, the issue also needs to fetch data when the page loads. Create a provisional that volition leave the function before the data fetch if list.length is truthy—indicating you have already fetched the data—and alert is fake—indicating you lot have already refreshed the information. Be sure to add warning and listing to the assortment of triggers:

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList,            setItem            }            from            '../../services/list'            ;            function            App            (            )            {            const            [warning,            setAlert]            =            useState            (            fake            )            ;            const            [itemInput,            setItemInput]            =            useState            (            ''            )            ;            const            [listing,            setList]            =            useState            (            [            ]            )            ;            useEffect            (            (            )            =>            {            let            mounted            =            truthful            ;                          if              (listing.length              &&              !alert)              {                                      render              ;                                      }                        getList            (            )            .            then            (            items            =>            {            if            (mounted)            {            setList            (items)            }            }            )            return            (            )            =>            mounted            =            faux            ;                          }              ,              [alert,              list]              )                        ...            return            (            <div className=            "wrapper"            >            ...            <            /div>            )            }            consign            default            App;                  

Save the file. When you do, the data volition refresh afterwards yous submit a new item:

List Refresh, 8

In this case, alert is not direct related to the list state. Notwithstanding, it does occur at the same time as an event that will invalidate the old data, so you can use it to refresh the data.

Preventing Updates on Unmounted Components

The concluding problem you demand to business relationship for is making certain you exercise not set state on an unmounted component. Yous have a solution to the problem with allow mounted = true in your event to fetch information, just the solution will not work for handleSubmit, since it is not an effect. You can't return a function to set the value to imitation when it is unmounted. Further, information technology would be inefficient to add the same check to every part.

To solve this problem, you can make a shared variable that is used past multiple functions past lifting mounted out of the useEffect Hook and belongings it on the level of the component. You'll still use the part to set the value to false at the stop of the useEffect.

Inside App.js, declare mounted at the start of the function. And then check if the component is mounted earlier setting information in the other asynchronous functions. Make certain to remove the mounted announcement within the useEffect function:

api-tutorial/src/components/App/App.js

                      import            React,            {            useEffect,            useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList,            setItem            }            from            '../../services/listing'            ;            function            App            (            )            {            const            [alert,            setAlert]            =            useState            (            false            )            ;            const            [itemInput,            setItemInput]            =            useState            (            ''            )            ;            const            [list,            setList]            =            useState            (            [            ]            )            ;                          let              mounted              =              truthful              ;                        useEffect            (            (            )            =>            {            if            (list.length            &&            !warning)            {            render            ;            }            getList            (            )            .            then            (            items            =>            {            if            (mounted)            {            setList            (items)            }            }            )            return            (            )            =>            mounted            =            fake            ;            }            ,            [            alarm,              list            ]            )            useEffect            (            (            )            =>            {            if            (warning)            {            setTimeout            (            (            )            =>            {                          if              (mounted)              {                        setAlert            (            false            )            ;                          }                        }            ,            one thousand            )            }            }            ,            [alert]            )            const            handleSubmit            =            (            e            )            =>            {            e.            preventDefault            (            )            ;            setItem            (itemInput)            .            so            (            (            )            =>            {                          if              (mounted)              {                        setItemInput            (            ''            )            ;            setAlert            (            true            )            ;                          }                        }            )            }            ;            return            (            <div className=            "wrapper"            >            ...            <            /div>            )            }            consign            default            App;                  

When you lot make the modify, you lot'll receive an mistake in the final where yous are running your React app:

                      

Error

Assignments to the 'mounted' variable from inside React Hook useEffect will be lost afterward each render. To preserve the value over fourth dimension, store information technology in a useRef Hook and go along the mutable value in the '.current' belongings. Otherwise, you tin move this variable directly inside useEffect react-hooks/exhaustive-deps

React is alerting you that variables are not stable. Whenever at that place is a re-return, it will recalculate the variable. Usually, this volition ensure upwards-to-engagement information. In this case, you are relying on that variable to persist.

The solution is another Hook called useRef. The useRef Hook will preserve a variable for the lifetime of the component. The only fob is to get the value you need to utilize the .electric current belongings.

Within App.js, convert mounted to a reference using the useRef Hook. Then catechumen each usage of mounted to mounted.current:

api-tutorial/src/components/App/App.js

                      import            React,            {            useEffect,            useRef,                        useState            }            from            'react'            ;            import            './App.css'            ;            import            {            getList,            setItem            }            from            '../../services/list'            ;            function            App            (            )            {            const            [alert,            setAlert]            =            useState            (            faux            )            ;            const            [itemInput,            setItemInput]            =            useState            (            ''            )            ;            const            [listing,            setList]            =            useState            (            [            ]            )            ;                          const              mounted              =              useRef              (              truthful              )              ;                        useEffect            (            (            )            =>            {            mounted.current              =              truthful              ;                        if            (list.length            &&            !alarm)            {            return            ;            }            getList            (            )            .            then            (            items            =>            {            if            (mounted              .electric current            )            {            setList            (items)            }            }            )            render            (            )            =>            mounted              .current            =            simulated            ;            }            ,            [alert,            list]            )            useEffect            (            (            )            =>            {            if            (warning)            {            setTimeout            (            (            )            =>            {            if            (mounted              .electric current            )            {            setAlert            (            false            )            ;            }            }            ,            1000            )            }            }            ,            [alert]            )            const            handleSubmit            =            (            e            )            =>            {            e.            preventDefault            (            )            ;            setItem            (itemInput)            .            then            (            (            )            =>            {            if            (mounted              .electric current            )            {            setItemInput            (            ''            )            ;            setAlert            (            true            )            ;            }            }            )            }            ;            return            (            <div className=            "wrapper"            >            ...            <            /div>            )            }            consign            default            App;                  

In add-on, be cautious near setting the variable in the cleanup role for useEffect. The cleanup role volition always run before the result reruns. That means that the cleanup function () => mounted.electric current = simulated will run every time the alert or list change. To avoid any false results, be sure to update the mounted.current to true at the start of the effect. Then you can exist sure information technology will only be set to fake when the component is unmounted.

Relieve and close the file. When the browser refreshes, you'll be able to salve new list items:

Saving again, 9

Note: It is a common problem to accidentally rerun an API multiple times. Every time a component is removed and then remounted, you will rerun all the original data fetching. To avoid this, consider a caching method for APIs that are particularly information heavy or deadening. You lot can use anything from memoizing the service calls, to caching with service workers, to a custom Claw. In that location are a few popular custom Hooks for caching service calls, including useSWR and react query.

No matter which approach you use, be certain to consider how you volition invalidate the cache because there are times where you'll want to fetch the newest data.

In this step, you lot sent data to an API. You learned how to update the user when the data is submitted and how to trigger a refresh on your list information. You also avoided setting data on unmounted components by using the useRef Claw to store the status of the component so that it can be used past multiple services.

Conclusion

APIs requite you the ability to connect to many useful services. They allow you lot to store and retrieve data fifty-fifty after a user closes their browser or stops using an application. With well organized code, you tin can isolate your services from your components and so that your components can focus on rendering data without knowing where the data is originating. Web APIs extend your application far beyond the capabilities of a browser session or storage. They open your application to the whole globe of web technologies.

If you would like to read more React tutorials, check out our React Topic page, or return to the How To Code in React.js serial page.

quirionunfinamess.blogspot.com

Source: https://www.digitalocean.com/community/tutorials/how-to-call-web-apis-with-the-useeffect-hook-in-react

0 Response to "Refresh Component Fetchs Data From Store Again"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel