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:
- Countries: list of our country to show them
- Load: to show a loading text until our fetch process completes. (to avoid async/await TypeErrors)
- 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
download the project here