How to fetch data from the network
Tags: react, axios, typescript
Published: 2020-01-27 11:54:57

---
title: How to fetch data from the network
published: true
description: 
tags: react, axios, typescript,
cover_image: https://thepracticaldev.s3.amazonaws.com/i/mm4tqdik8ixqa6p83mhg.jpg
series: React and Material UI
---

# Introduction

In this article, I'm going to build the Home page of the application.
It will display the list of all the available seasons of the competition Serie A.

# Setting up `axios`

To make HTTP calls I have two options: `fetch` or `axios`. For this article I choose to pick up `axios`

```bash
npm install axios
```

Once installed, I create a new module, `httpService.ts`

```typescript
import axios from 'axios';

const httpService = axios.create({
  baseURL: 'http://api.football-data.org',
  timeout: 1000,
  headers: {
    'X-Auth-Token': 'FOOTBALL DATA API KEY', // your account API Key
  },
});

export default httpService;
```

This module exports an `axios configuration` that we can use throughout the application. Using this configuration I don't have to write every time same things like `headers` or the `timeout` of the request.

# The `Home` component

In the first place, I'd like to take the Home component out from `Routes.tsx`.

```typescript
import React, { Component } from 'react';

import {
  Container,
  Grid,
} from '@material-ui/core';

interface IProps {};

interface IState {
  matchday: number,
  matches: any[],
  competition: any,
  error: boolean,
  totalMatchdays: number,
};

class Home extends Component<IProps, IState> {
  constructor(props: IProps) {
    super(props);
    this.state = {
      matchday: 1,
      matches: [],
      competition: null,
      error: false,
      totalMatchdays: 38,
    };
  }

  render() {
    return (
      <Container>
        Home
      </Container>
    );
  }
};
```
Now, using `httpService` I can fetch data.

```typescript
...
import httpService from '../../../services/httpService';
import { AxiosResponse } from 'axios';
...
fetch = () => {
  httpService
    .get(`/v2/competitions/2019/matches?matchday=${this.state.matchday}`)
    .then((response: AxiosResponse) => {
      this.setState({
        competition: response.data.competition,
        matches: response.data.matches,
      });
    })
    .catch((error: AxiosResponse) => {
      this.setState({ error: true });
    });
};
```

This function has to be called everytime the state changes and the component is re-rendered: `componentDidMount`.

```typescript
componentDidMount() {
  this.fetch();
};
```

Adding some `console.log` I can see the response in the browser console

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/opx8ju86f4sz5o5h3enl.png)

Now that I have the complete response, I can add more specific interfaces to my `IState`.

```typescript
interface ICompetition {
  id: number;
  area: object;
  name: string;
  code: string;
  plan: string;
  lastUpdated: string;
};

interface IScore {
  winner: string;
  duration: string;
  fullTime: {
    homeTeam: number | null;
    awayTeam: number | null;
  };
  halfTime: {
    homeTeam: number | null;
    awayTeam: number | null;
  };
  extraTime: {
    homeTeam: number | null;
    awayTeam: number | null;
  };
  penalties: {
    homeTeam: number | null;
    awayTeam: number | null;
  };
};

interface ITeam {
  id: number;
  name: string;
};

interface IReferee {
  id: number;
  name: string;
  nationality: string | null;
};

interface IMatch {
  id: number;
  season: object;
  utcDate: string;
  status: 'SCHEDULED' | 'LIVE' | 'IN_PLAY' | 'PAUSED' | 'FINISHED' | 'POSTPONED' | 'SUSPENDED' | 'CANCELED';
  matchday: number;
  stage: string;
  group: string;
  lastUpdated: string;
  score: IScore;
  homeTeam: ITeam;
  awayTeam: ITeam;
  referees: IReferee[];
};

interface IState {
  matchday: number,
  matches: IMatch[] | [],
  competition: ICompetition | null,
  error: boolean,
  totalMatchdays: number,
};
```

# Displaying matches details

I can now access these information from the `state`

```typescript
<ul>
  {matches.map((match: IMatch) => (
    <li key={match.id}>
      {match.homeTeam.name} <b>{match.score.fullTime.homeTeam}</b> - <b>{match.score.fullTime.awayTeam}</b> {match.awayTeam.name}
    </li>
  ))}
</ul>
```

The list I obtain is the following.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/4toqp685talz4vv42564.png)

For now, this component is limited because I can display only matches of the first matchday. But what if I want to choose the matchday I'd like to display?

# Updating the list when state changes

I create a new function

```typescript
handleChange = (event: any) => {
  this.setState({ matchday: event.target.value }, () => {
    this.fetch();
  });
};
```

This handler fetches date from the APIs everytime is called.

Then, I add a new element in the UI: a `select`.

```typescript
render() {
  const options = [];
  for (let index = 1; index <= this.state.totalMatchdays; index++) {
    options.push(<option key={index}>{index}</option>)
  }
...
  <select onChange={this.handleChange} value={this.state.matchday}>
    {options}
  </select>
```

Everytime this `select` changes, the state is popoluated with new macthes of a different matchday.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/elopvqb8aur4k87ufmqo.gif)

# Conclusion

Now that I added a basic functionality to the Home component, I can think how to improve it.

For example, the `select` can be replaced by the Material UI `Select` component https://material-ui.com/components/selects/; the `ul` can be improved by using Material UI `Card` component https://material-ui.com/components/cards/.