RESTful Data

Binding data from RESTful API to Grid in React JS

A combination of a lifecycle hook and the fetch() allow us to bind the data from an external data source

What is a lifecycle hook?

When you work with a functional component and want to "hook into" a lifecycle features you can catch each lifecycle phase in useEffect.

There are three phases: mounting, updating and unmounting.

As a second argument of the useEffect() we can pass a dependency array.
It is used to detect changes in the component and the callback will be executed when a variable from the dependency array updates its value.

An example of using useEffect: The callback passed to the useEffect will be invocked only once after mounting in this situation and the cleanup function will be executed when the component unmounts.

    import './App.css';
    import { useEffect } from 'react';
    
    function App() {
    
        useEffect(() => {
    
            console.log('Mounted');
        
            return function cleanup() {
                
                console.log('Do some cleanup.');
        
            }

        }, []);
    
        return (
            <h1>My cool component</h1>
        );
    }
    
    export default App;    
                    

What is a fetch()?

The Fetch API provides an interface for fetching resources. It seems similar to XMLHttpRequest, but Fetch provides more powerful and flexible set.

Usage: The fetch() takes one mandatory argument - the path to the resource and one optional argument for initializing the Request object. The method returns a Promise that resolves to a Response object when the server responds. The Response object contains many methods as well as json(). The json() method returns a new Promise that resolves to the body of the response parsed to JSON.

Let's fetch all the countries around the world

    import './App.css';
    import { useEffect, useState } from 'react';
    
    function App() {
        
        const [countries, setCountries] = useState([]);

        useEffect(() => {

            fetch('https://restcountries.com/v3.1/all')
              .then(res => res.json())
              .then(countries => {
                
                setCountries(countries.slice(0,50));
        
              });
        
          }, []);
    
        return (
            <h1>My cool component</h1>
            <ul>
                {
                    countries
                        .map(c => <li key={c.area}>{c.name.common}</li>)
                }
            </ul>
        );
    }
    
    export default App;    
                    

How to combine useEffect and the Fetch API to bind remote data to Grid?

In the following example we will display an information about a country in a Grid.

To achieve that we should first fetch all the countries via the public API called REST Countries.

We will store the countries in a local state so we can use them in the Grid component.

Fetching the countries should be done when the component mounts. To do that we will use useEffect with an empty dependency array. The array will be empty because the API url won't change during the component's lifecycle.

In the useEffect's callback we are using the fetch() method to get the countries from the public API.

We are converting the response's data to a JSON.

Next we are summarizing the needed data of each country, then after the mapping the data is being cut to 50 records.

The last step is to save the data in the state and pass the countries data as well as the settings for the filtering, sorting and editing to the Grid component.

    import 'smart-webcomponents-react/source/styles/smart.default.css';
    import { Grid } from 'smart-webcomponents-react/grid';
    import { useEffect, useState } from 'react';
    
    function App() {
    
        const apiUrl = 'https://restcountries.com/v3.1/all';
    
        const sorting = {
            enabled: true,
            sortMode: 'one'
        };
    
        const filtering = {
            enabled: true,
            filter: [
            ]
        };
    
        const editing = {
            enabled: true,
            mode: 'cell'
        };
    
        const columns = [{
            label: 'Name',
            dataField: 'name'
        },
        {
            label: 'Continent',
            dataField: 'continent'
        },
        {
            label: 'Area',
            dataField: 'area'
        },
        {
            label: 'Capital',
            dataField: 'capital'
        },
        {
            label: 'Currency',
            dataField: 'currency',
        },
        {
            label: 'Population',
            dataField: 'population',
        }
        ];
    
        const [gridData, setGridData] = useState([]);
    
        useEffect(() => {
    
        fetch(apiUrl)
            .then(res => res.json())
            .then(countries => {
        
                countries = countries
                    .slice(0, 50)
                    .map(
                    c => {
        
                        const currency = c.currencies ? Object.entries(c.currencies)[0][1].name : '';
        
                        return ({
                        name: c.name.common,
                        continent: c.region,
                        capital: c.capital ? c.capital[0] : '',
                        currency: currency,
                        area: c.area,
                        population: c.population
                        })
                    }
                    );
        
                setGridData(
                    countries
                );
    
            });
    
        }, []);
    
        return (
        <Grid id="grid"
            sorting={sorting}
            filtering={filtering}
            editing={editing}
            dataSource={gridData}
            columns={columns}></Grid>
        );
    }
    
    export default App;                 
                    

The result of the code is this: