In this guide, we’ll walk through how to consume a Laravel REST API in an Expo/React Native application. We’ll create a simple Laravel API that returns a list of Pokémon, and then we’ll display that list in a React Native app using NativeWind for styling. By the end of this tutorial, you’ll have a working example of how to fetch data from a Laravel backend and render it in a mobile app.
Prerequisites
Before we start, make sure you have the following installed:
- Laravel: A PHP framework for building the API.
- Expo CLI: For setting up and running the React Native app.
- Node.js: Required for running the React Native app.
- Composer: For managing Laravel dependencies.
- NativeWind: A utility-first CSS framework for React Native.
- Guzzle HTTP Client: For making HTTP requests in Laravel to fetch Pokémon data from PokéAPI.
Step 1: Set Up the Laravel API
1.0 Create a New Laravel Project
Open your terminal and run the following command to create a new Laravel project:
composer create-project --prefer-dist laravel/laravel pokemon-api
Navigate into the project directory:
cd pokemon-api
1.1 Install Guzzle HTTP Client
Guzzle is a PHP HTTP client that makes it easy to send HTTP requests. Install it via Composer:
composer require guzzlehttp/guzzle
1.2 Create a Pokémon Model and Migration
Generate a model and migration for the Pokémon data:
php artisan make:model Pokemon -m
This command creates a Pokemon model and a migration file in the database/migrations directory.
1.3 Define the Pokémon Table Schema
Open the migration file (e.g., database/migrations/xxxx_xx_xx_create_pokemons_table.php) and define the schema:
public function up()
{
Schema::create('pokemons', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('type');
$table->string('image_url');
$table->timestamps();
});
}
Run the migration to create the table:
php artisan migrate
Open the Pokemon model (app/Models/Pokemon.php) and add the image_url field to the $fillable array:
protected $fillable = ['name', 'type', 'image_url'];
1.4 Seed the Database with Pokémon Data
Create a seeder to populate the pokemons table with sample data:
php artisan make:seeder PokemonSeeder
Open the seeder file (database/seeders/PokemonSeeder.php) and add the following:
use App\Models\Pokemon;
use GuzzleHttp\Client;
public function run()
{
$client = new Client();
$pokemonCount = 20; // Number of Pokémon to fetch
for ($i = 1; $i <= $pokemonCount; $i++) {
$response = $client->get("https://pokeapi.co/api/v2/pokemon/{$i}");
$data = json_decode($response->getBody(), true);
$name = $data['name'];
$type = $data['types'][0]['type']['name']; // Get the first type
$imageUrl = $data['sprites']['front_default']; // Get the image URL
Pokemon::create([
'name' => ucfirst($name),
'type' => ucfirst($type),
'image_url' => $imageUrl,
]);
}
}
Run the seeder:
php artisan db:seed --class=PokemonSeeder
1.5 Create a REST API Endpoint
Open the routes/api.php file and define a route to fetch the Pokémon list. Ensure the `/api/pokemons` route returns the Pokémon data:
use App\Models\Pokemon;
Route::get('/pokemons', function () {
return Pokemon::all();
});
1.6 Test the API
Start the Laravel development server:
php artisan serve
Visit http://localhost:8000/api/pokemons in your browser or use a tool like Postman to verify that the API returns the Pokémon data in JSON format.
Step 2: Set Up the Expo/React Native App
2.1 Create a New Expo Project
Run the following command to create a new Expo project:
npx create-expo-app@latest pokemon-app
Navigate into the project directory:
cd pokemon-app
2.2 Install Dependencies
Install the required dependencies for NativeWind and React Navigation (optional for navigation):
npm install nativewind
npm install @react-navigation/native @react-navigation/stack
npm install react-native-screens react-native-safe-area-context
2.3 Configure NativeWind
Update your babel.config.js file to include NativeWind:
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['nativewind/babel'],
};
};
Create a tailwind.config.js file:
module.exports = {
content: [
'./App.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}',
],
theme: {
extend: {},
},
plugins: [],
};
2.4 Create a Pokémon Card Component
Create a new file components/PokemonCard.js:
import React from 'react';
import { View, Text, Image } from 'react-native';
const PokemonCard = ({ name, type, imageUrl }) => {
return (
<View className="bg-white p-4 rounded-lg shadow-md mb-4">
<Image
source={{ uri: imageUrl }}
className="w-full h-40 mb-2 rounded-lg"
resizeMode="contain"
/>
<Text className="text-xl font-bold">{name}</Text>
<Text className="text-gray-600">Type: {type}</Text>
</View>
);
};
export default PokemonCard;
2.5 Fetch Data from the Laravel API
Open App.js and replace its content with the following:
import React, { useEffect, useState } from 'react';
import { View, ScrollView, ActivityIndicator } from 'react-native';
import PokemonCard from './components/PokemonCard';
export default function App() {
const [pokemons, setPokemons] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('http://localhost:8000/api/pokemons')
.then((response) => response.json())
.then((data) => {
setPokemons(data);
setLoading(false);
})
.catch((error) => {
console.error(error);
setLoading(false);
});
}, []);
if (loading) {
return (
<View className="flex-1 justify-center items-center">
<ActivityIndicator size="large" color="#0000ff" />
</View>
);
}
return (
<ScrollView className="p-4">
{pokemons.map((pokemon) => (
<PokemonCard
key={pokemon.id}
name={pokemon.name}
type={pokemon.type}
imageUrl={pokemon.image_url}
/>
))}
</ScrollView>
);
}
2.6 Run the App
Start the Expo development server:
npx expo start
Scan the QR code with the Expo Go app or run it on an emulator to see the Pokémon list displayed as cards. You should now see a list of 20 Pokémon displayed in cards, each with their name, type, and image. The cards are styled using NativeWind, making the UI clean and responsive.
Optional Enhancements
- Pagination: Implement pagination in the Laravel API to handle large datasets.
- Search: Add a search bar in the React Native app to filter Pokémon by name or type.
- Details Screen: Use React Navigation to create a details screen for each Pokémon.
That’s it! You’ve successfully built a Laravel API that fetches Pokémon data from PokéAPI and displays it in a React Native app with images. This setup can be extended further to build a full-fledged Pokémon app.
Happy coding! 🚀