DEV Community

Cover image for React & REST API: How to render responses
William Sayama
William Sayama

Posted on

React & REST API: How to render responses

Overview

This series will walk through how to make REST API calls from a React component to a 3rd party service, and render the result into the UI.

Our core focus will be on making the call, so we'll keep the rendering process very simple in this series (i.e. no tables, no colors, just displaying the plain JSON response).

The final image

Our React project will use an Express server as a proxy, so that it will make REST API calls to our desired service. The response from the service will be routed through our Express server back to our React project, where it will be rendered into the UI.

Alt Text

The directory structure

The final directory tree looks roughly like this.



.
└── myproject/
    ├── frontend/
    │   ├── index.js
    │   └── index.html
    └── backend/
        ├── server.js
        └── .env


Enter fullscreen mode Exit fullscreen mode

I say "roughly", because technically more files actually exist in this project, and some files shown above exist a bit deeper in the tree. I just wanted to make it clear that these will be the main files in the project.

OK, so let's start ٩( 'ω' )و

Set up a Node environment

Create a directory to work in

We'll start off by creating a directory to place our frontend and backend projects in, and move to that directory.



mkdir myproject
cd myproject


Enter fullscreen mode Exit fullscreen mode

If you're using Visual Studio Code, you can enter the following into the terminal to open up your project in the editor which makes managing the project easier.



code .


Enter fullscreen mode Exit fullscreen mode

Install Node

Install Node into this directory.
Since we'll be using react, Node needs to be version 10.16 or later. It's up to you on how you install Node - I personally like using nodenv to manage my node projects.



nodenv local 14.5.0


Enter fullscreen mode Exit fullscreen mode

Great, now that we have that set up, let's carry on!

Set up a React App

Create React App

We'll use create-react-app to build our React application simply and quickly. Run the following command in the myproject directory.



npx create-react-app frontend


Enter fullscreen mode Exit fullscreen mode

This may take a few minutes, but in our myproject directory we should end up with a directory named frontend, with a whole lot of files inside.

Alt Text

Run the App

Move into the newly created directory and start the React App.



cd frontend
npm start


Enter fullscreen mode Exit fullscreen mode

If your browser has started to run and is showing the screen below, we're ready to move on. If not, access http://localhost:3000/ to view this page. Make a note that this project will be running on port 3000.

Alt Text

Delete unnecessary files

Since our objective in this article isn't focused on making fancy looking applications, let's delete everything in our src directory except for the index.js file.

Alt Text

Run some React code

Open up index.js in the editor and delete every line of code in there, so we can start from scratch. Let's run a simple code that uses React to render content into the UI.



import React from 'react';
import ReactDOM from 'react-dom';

const myelement = <h1><u>These are the details of the myelement const</u></h1>;

ReactDOM.render(
    myelement,
    document.querySelector('#root')
);


Enter fullscreen mode Exit fullscreen mode

Refresh the browser running the react App, and we should get this.

Alt Text

So far so good - now our next step is to start working on API calls.

Make REST API calls to Random User Generator API

Random User Generator API

Random User Generator API is an API service that generates random fake user information - a quick and easy place to test out REST API calls from our React project.

Fetch data from Random User Generator API

We'll first make our API call to the following endpoint: https://randomuser.me/api/

We'll add in a function to make a REST API call to this endpoint, and we'll display the result in the console.



import React from 'react';
import ReactDOM from 'react-dom';

//-----Added in code from here-------
const restEndpoint = "https://randomuser.me/api/";

const callRestApi = async () => {
    const response = await fetch(restEndpoint);
    const jsonResponse = await response.json();
    console.log(jsonResponse);
};

callRestApi();
//--------------to here---------------

const myelement = <h1><u>These are the details of the myelement const</u></h1>;

ReactDOM.render(
    myelement,
    document.querySelector('#root')
);


Enter fullscreen mode Exit fullscreen mode

Reload your browser running the React App, and you should see this in your console.

Alt Text

By making a request to the https://randomuser.me/api/ endpoint, we're given back data of a random user. Every time we refresh the browser, we should see new information of a random user being displayed in the console.

Now since we're using React, let's try rendering the result into the browser UI.

Render the response

So we should be able to render the result if we were to pass the result into ReactDOM.render(), right? Let's update our code so that the first parameter of this method will call our callRestApi function. We'll adjust our callRestApi function to return a React element by using React.createElement, with our third parameter being a stringified version of our REST API response. We'll also remove any unused functions and variables.



import React from 'react';
import ReactDOM from 'react-dom';

const restEndpoint = "https://randomuser.me/api/";

const callRestApi = async () => {
    const response = await fetch(restEndpoint);
    const jsonResponse = await response.json();
    console.log(jsonResponse);
    return React.createElement('h1', null, JSON.stringify(jsonResponse));
};

ReactDOM.render(
    callRestApi(),
    document.querySelector('#root')
);


Enter fullscreen mode Exit fullscreen mode

So this should in theory get the REST API response, and then render the result into the root element. Let's see the result.

Alt Text

Alt Text

Objects are not valid as a React child (found: [object Promise]) ... Whaaaaat...?

So let's see what went wrong.

ReactDOM.render() calls the callRestApi() function to obtain the element to render on the root.



ReactDOM.render(
    callRestApi(),
    document.querySelector('#root')
);


Enter fullscreen mode Exit fullscreen mode

As callRestApi() is an async function, it immediately returns a promise object while it goes off to make the REST API call.



const callRestApi = async () => {
    //...
};


Enter fullscreen mode Exit fullscreen mode

REST API calls are not instant. Because there's a server on the other end processing the request, it takes time for the result to be responded back. React doesn't "wait" for the REST API result to come back though when it's told to render an element - this results in ReactDOM.render() trying to render this pending promise object immediately, and failing.

So what do we do?

For React to take care of REST API calls, we need to use the useState Hooks and useEffect Hooks in our code.

For those who are unfamiliar with these notations:

  • useState hooks allow us to use special "state" variables that we can utilize to render into the React UI.
  • useEffect hooks allow us to run functions after rendering has finished. We'll use this to run a REST API call and update the state variable, which will then cause React to re-render the UI with the new state variable.


import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

const restEndpoint = "https://randomuser.me/api/";

const callRestApi = async () => {
    const response = await fetch(restEndpoint);
    const jsonResponse = await response.json();
    console.log(jsonResponse);
    return JSON.stringify(jsonResponse);
};

function RenderResult() {
  const [apiResponse, setApiResponse] = useState("*** now loading ***");

  useEffect(() => {
      callRestApi().then(
          result => setApiResponse(result));
  },[]);

  return(
      <div>
          <h1>React App</h1>
          <p>{apiResponse}</p>
      </div>
  );
};

ReactDOM.render(
    <RenderResult/>,
    document.querySelector('#root')
);


Enter fullscreen mode Exit fullscreen mode

Running this should give us the following result, with data of a random user displayed. We can reload the page to display datasets of other random users.

Alt Text

Great!

You'll notice there's a lag before the user data is displayed on the UI. This lag is caused by the REST API call which takes a bit of time to get the response back from the server it's requesting to. The UI will not re-render until the code retrieves the response.

We won't go into too much details about what each hook related statement does, as it's probably easier to understand through the React docs. But here is an overview of what we are doing.

Our initial state value is the string "*** now loading ***", which is displayed in the UI due to the initial rendering.



const [apiResponse, setApiResponse] = useState("*** now loading ***");


Enter fullscreen mode Exit fullscreen mode

After the rendering finishes, useEffect() runs the REST API call, waits for the response to come back (which is causing the lag), then updates the state variable with the new response.



useEffect(() => {
    callRestApi().then(
        result => setApiResponse(result));
},[]);


Enter fullscreen mode Exit fullscreen mode

React automatically re-renders the UI whenever there's a state change, and thus updates the UI with the response from the REST API call. The second argument of useEffect() controls when the re-rendering should be done - in this case, we passed in an empty array so that the re-rendering is only invoked once.

Next steps

In this article, we've gone through methods on how to make REST API calls to a REST endpoint from a React component, and render it into the UI.

In part 2 of this series, we'll run into common issues that developers run into when trying to call other REST endpoints.

                   _人人人人人人人_
                   > CORS ERRORS <
                    ̄Y^Y^Y^Y^Y^Y^ ̄
                   (\__/) 
                   (•ㅅ•) 
                   /つ つ
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
tamarutaca profile image
João Vítor Fernandes Dias

Nice tutorial. I am trying to do a JSON processing website for my monograph, and this tutorial is coming handy. Thank you.