Functional component useEffect Hook & axios API Call Example

Functional component useEffect Hook & axios API Call Example

Functional component useEffect Hook & axios

Introduction

In this example we will perform an API call using one of the commonly used 3rd party libraries called axios.

We will do so in a functional component using the useState & useEffect hook.

We will consume an API that returns a list of countries:

We will create a new project with npx called axiosAPICallExample

npx react-native init axiosAPICallExample

Next, in order to be able to use axios we will install it in our project using npm.

navigate inside the new created project and run:

npm install axios

After install axios, we will open our project folder in VS code to start to add our code in App.js

in this example we will be implementing in JS and using functional components instead of class components to ilustrate the use of functional components with hooks and specifically the use of useEffect hook to perform API calls.

in App.js delete the default project content added as part of project creation with react-native init.

and let's start to code.

first we will add the imports required.

in this example we are adding the hooks useEffect & useState and axios

import React, {useEffect, useState} from 'react';
import {
  FlatList,
  View,
  Text,
  StyleSheet,
  ActivityIndicator,
} from 'react-native';
import axios from 'axios';

then inside our app constant we will define the state using useState hook as below:

We need to provide 3 variables in our state:

  1. Countries: list of our country to show them
  2. Load: to show a loading text until our fetch process completes. (to avoid async/await TypeErrors)
  3. Error: to show error returns from our fetch method instead of the country list
 const [countries, setCountries] = useState([]);
  const [load, setLoad] = useState(false);
  const [error, setError] = useState('');

in this example we will use a basic component called Flatlist to display list of returned values.

So we will add a couple of methods used to support this component

const Item = ({title}) => (
    <View style={styles.item}>
      <Text style={styles.title}>{title}</Text>
    </View>
  );
  const renderItem = ({item}) => <Item title={item.name} />;

Then we will use useEffect Hook to consume the API via axios

Don’t forget to pass an empty array as second argument because we want our useEffect act like componentDidMount.

 useEffect(() => {
    axios
      .get('https://restcountries.eu/rest/v2/all')
      .then((res) => {
        setCountries(res.data);
        setLoad(true);
      })
      .catch((err) => {
        setError(err.message);
        setLoad(true);
      });
  }, []);

Finally in our app functional component we will add the UI part that will be returned

Our load initial state is a Boolean type false and our error is undefined. When our component mounted, we fetch our API. If API returns status code 200 or OK, we set our countries array by returned data. But if our fetch process fails, we set an error equal to retuned error. In both cases we set our load “true” to show visitors the final result.

if (load) {
    return error ? (
      error.message
    ) : (
      <FlatList
        data={countries}
        renderItem={renderItem}
        keyExtractor={(item) => item.name}
      />
    );
  } else {
    return <ActivityIndicator />;
  }

And our styles.

with that the whole page will look like this

import React, {useEffect, useState} from 'react';
import {
  FlatList,
  View,
  Text,
  StyleSheet,
  ActivityIndicator,
} from 'react-native';
import axios from 'axios';
​
const App: () => React$Node = () => {
  const [countries, setCountries] = useState([]);
  const [load, setLoad] = useState(false);
  const [error, setError] = useState('');
​
  const Item = ({title}) => (
    <View style={styles.item}>
      <Text style={styles.title}>{title}</Text>
    </View>
  );
  const renderItem = ({item}) => <Item title={item.name} />;
  useEffect(() => {
    axios
      .get('https://restcountries.eu/rest/v2/all')
      .then((res) => {
        setCountries(res.data);
        setLoad(true);
      })
      .catch((err) => {
        setError(err.message);
        setLoad(true);
      });
  }, []);
​
  if (load) {
    return error ? (
      error.message
    ) : (
      <FlatList
        data={countries}
        renderItem={renderItem}
        keyExtractor={(item) => item.name}
      />
    );
  } else {
    return <ActivityIndicator />;
  }
};
​
const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 10,
  },
  item: {
    backgroundColor: '#000000',
    padding: 20,
    marginVertical: 8,
    marginHorizontal: 16,
  },
  title: {
    fontSize: 32,
    color: '#FFFFFF',
  },
});
​
export default App;

to run our app navigate to the project folder with CMD and run the below command to start Metro server:

npx react-native start

Then leave metro server running and in a new CMD run the below command to build the app and deploy it in our emulator

npx react-native run-android

this will be our result app

image.png

download the project here