React Native Basics (Part 4): Consuming APIs with Fetch - Using PokeAPI
In Part 3, we implemented navigation and a simple CRUD using static data. Now, let’s take things a step further by consuming an external API. We’ll use PokeAPI to fetch and display a list of Pokémon in our React Native app.
1. Setting Up the API Consumption
React Native provides the built-in fetch
API to make network requests. In this section, we’ll fetch Pokémon data from PokeAPI and display it in a list.
Step 1: Create a New Screen for API Consumption
First, let’s create a new file, PokemonScreen.js
, where we’ll write the logic to fetch data from PokeAPI and display it.
Step 2: Fetch Data from PokeAPI
In PokemonScreen.js
, we’ll set up the component to fetch data from the API and display it using React Native components.
PokemonScreen.js
import React, { useState, useEffect } from "react";
import {
View,
Text,
FlatList,
StyleSheet,
ActivityIndicator,
} from "react-native";
const PokemonScreen = () => {
const [pokemonList, setPokemonList] = useState([]);
const [loading, setLoading] = useState(true);
// Fetch data from PokeAPI
const fetchPokemon = async () => {
try {
const response = await fetch(
"https://pokeapi.co/api/v2/pokemon?limit=20"
);
const data = await response.json();
setPokemonList(data.results);
setLoading(false);
} catch (error) {
console.error("Error fetching Pokemon data:", error);
setLoading(false);
}
};
useEffect(() => {
fetchPokemon();
}, []);
return (
<View style={styles.container}>
{loading ? (
<ActivityIndicator size="large" color="#0000ff" />
) : (
<FlatList
data={pokemonList}
keyExtractor={item => item.name}
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<Text style={styles.itemText}>{item.name}</Text>
</View>
)}
/>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
itemContainer: {
padding: 10,
borderBottomWidth: 1,
borderBottomColor: "#ccc",
},
itemText: {
fontSize: 18,
},
});
export default PokemonScreen;
Step 3: Adding the Screen to Navigation
Now, let’s add the PokemonScreen
to our navigator in App.js
.
App.js
import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createStackNavigator } from "@react-navigation/stack";
import HomeScreen from "./HomeScreen";
import CRUDScreen from "./CRUDScreen";
import PokemonScreen from "./PokemonScreen";
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="CRUD" component={CRUDScreen} />
<Stack.Screen name="Pokemon" component={PokemonScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
export default App;
Step 4: Navigating to the Pokémon Screen
In HomeScreen.js
, let’s add a button to navigate to the Pokémon screen.
HomeScreen.js
import React from "react";
import { View, Button } from "react-native";
const HomeScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Button
title="Go to CRUD Screen"
onPress={() => navigation.navigate("CRUD")}
/>
<Button
title="Go to Pokemon Screen"
onPress={() => navigation.navigate("Pokemon")}
/>
</View>
);
};
export default HomeScreen;
2. Explanation of the Code
useState
anduseEffect
: We use theuseState
hook to manage the state ofpokemonList
andloading
. TheuseEffect
hook is used to callfetchPokemon
when the component is mounted.fetch
API: ThefetchPokemon
function makes a GET request to the PokeAPI. It fetches the first 20 Pokémon and updates the state with the retrieved data.FlatList
: This component renders the list of Pokémon names. We use thekeyExtractor
prop to define a unique key for each item, and therenderItem
prop to display each Pokémon’s name.ActivityIndicator
: Displays a loading spinner while the data is being fetched.
3. Customizing the Display
You can enhance this screen by displaying more details, such as each Pokémon’s image. The PokeAPI provides additional details for each Pokémon, which you can fetch using their URLs.
Step 5: Fetching More Details (Optional)
To fetch individual Pokémon details, modify the fetchPokemon
function to include more data:
const fetchPokemon = async () => {
try {
const response = await fetch("https://pokeapi.co/api/v2/pokemon?limit=20");
const data = await response.json();
// Fetch additional details for each Pokémon
const detailedPokemonList = await Promise.all(
data.results.map(async pokemon => {
const pokemonDetails = await fetch(pokemon.url);
return await pokemonDetails.json();
})
);
setPokemonList(detailedPokemonList);
setLoading(false);
} catch (error) {
console.error("Error fetching Pokemon data:", error);
setLoading(false);
}
};
Step 6: Displaying Additional Data
Now, let’s display each Pokémon’s name and image in the FlatList
.
Update the FlatList
’s renderItem
:
<FlatList
data={pokemonList}
keyExtractor={item => item.name}
renderItem={({ item }) => (
<View style={styles.itemContainer}>
<Text style={styles.itemText}>{item.name}</Text>
<Image
source={{ uri: item.sprites.front_default }}
style={{ width: 50, height: 50 }}
/>
</View>
)}
/>
Conclusion
In this part, we learned how to consume an external API using the fetch
method and display the data in our React Native app. We fetched a list of Pokémon from the PokeAPI, displayed their names, and even extended the functionality to fetch and display additional details like images.
In future parts, we can explore more advanced API handling, such as error handling, pagination, and interacting with user inputs to fetch specific data. Until then, keep experimenting with React Native and the limitless possibilities it offers!
Happy coding! 🎉