In this project, we will build a simple e-commerce application using React Native. This project will help you understand how to integrate various concepts learned in the previous modules, such as state management, navigation, networking, and more.

Objectives

  • Create a user-friendly interface for browsing products.
  • Implement navigation between different screens.
  • Fetch product data from an API.
  • Handle user actions such as adding items to the cart.
  • Manage state for the shopping cart.
  • Persist cart data using AsyncStorage.

Project Structure

  1. Setting Up the Project
  2. Creating the Product List Screen
  3. Implementing Product Details Screen
  4. Building the Shopping Cart
  5. Persisting Cart Data
  6. Final Touches and Testing

  1. Setting Up the Project

Step 1: Initialize the Project

First, create a new React Native project using the following command:

npx react-native init EcommerceApp

Step 2: Install Required Packages

Install the necessary packages for navigation and state management:

npm install @react-navigation/native @react-navigation/stack @react-navigation/bottom-tabs
npm install react-native-gesture-handler react-native-reanimated react-native-screens react-native-safe-area-context @react-native-community/masked-view
npm install axios
npm install @react-native-async-storage/async-storage

Step 3: Set Up Navigation

Create a navigation folder and add a MainNavigator.js file:

// navigation/MainNavigator.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import ProductListScreen from '../screens/ProductListScreen';
import ProductDetailsScreen from '../screens/ProductDetailsScreen';
import CartScreen from '../screens/CartScreen';

const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();

const MainNavigator = () => {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Products" component={ProductStackNavigator} />
        <Tab.Screen name="Cart" component={CartScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
};

const ProductStackNavigator = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen name="ProductList" component={ProductListScreen} />
      <Stack.Screen name="ProductDetails" component={ProductDetailsScreen} />
    </Stack.Navigator>
  );
};

export default MainNavigator;

Step 4: Update App.js

Update App.js to use the MainNavigator:

// App.js
import React from 'react';
import MainNavigator from './navigation/MainNavigator';

const App = () => {
  return <MainNavigator />;
};

export default App;

  1. Creating the Product List Screen

Step 1: Create ProductListScreen Component

Create a screens folder and add a ProductListScreen.js file:

// screens/ProductListScreen.js
import React, { useEffect, useState } from 'react';
import { View, Text, FlatList, TouchableOpacity, StyleSheet } from 'react-native';
import axios from 'axios';

const ProductListScreen = ({ navigation }) => {
  const [products, setProducts] = useState([]);

  useEffect(() => {
    axios.get('https://fakestoreapi.com/products')
      .then(response => setProducts(response.data))
      .catch(error => console.error(error));
  }, []);

  const renderItem = ({ item }) => (
    <TouchableOpacity onPress={() => navigation.navigate('ProductDetails', { product: item })}>
      <View style={styles.item}>
        <Text style={styles.title}>{item.title}</Text>
      </View>
    </TouchableOpacity>
  );

  return (
    <FlatList
      data={products}
      renderItem={renderItem}
      keyExtractor={item => item.id.toString()}
    />
  );
};

const styles = StyleSheet.create({
  item: {
    padding: 20,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc',
  },
  title: {
    fontSize: 18,
  },
});

export default ProductListScreen;

  1. Implementing Product Details Screen

Step 1: Create ProductDetailsScreen Component

Create a ProductDetailsScreen.js file in the screens folder:

// screens/ProductDetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

const ProductDetailsScreen = ({ route, navigation }) => {
  const { product } = route.params;

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{product.title}</Text>
      <Text style={styles.description}>{product.description}</Text>
      <Text style={styles.price}>${product.price}</Text>
      <Button title="Add to Cart" onPress={() => {/* Add to cart logic */}} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
  },
  description: {
    fontSize: 16,
    marginVertical: 10,
  },
  price: {
    fontSize: 20,
    color: 'green',
    marginVertical: 10,
  },
});

export default ProductDetailsScreen;

  1. Building the Shopping Cart

Step 1: Create CartScreen Component

Create a CartScreen.js file in the screens folder:

// screens/CartScreen.js
import React, { useState } from 'react';
import { View, Text, FlatList, Button, StyleSheet } from 'react-native';

const CartScreen = () => {
  const [cartItems, setCartItems] = useState([]);

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

  return (
    <View style={styles.container}>
      <FlatList
        data={cartItems}
        renderItem={renderItem}
        keyExtractor={item => item.id.toString()}
      />
      <Button title="Checkout" onPress={() => {/* Checkout logic */}} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  item: {
    padding: 20,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc',
  },
  title: {
    fontSize: 18,
  },
  price: {
    fontSize: 16,
    color: 'green',
  },
});

export default CartScreen;

  1. Persisting Cart Data

Step 1: Install AsyncStorage

Ensure AsyncStorage is installed:

npm install @react-native-async-storage/async-storage

Step 2: Update Cart Logic

Update the CartScreen and ProductDetailsScreen to use AsyncStorage for persisting cart data:

// screens/CartScreen.js
import React, { useState, useEffect } from 'react';
import { View, Text, FlatList, Button, StyleSheet } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';

const CartScreen = () => {
  const [cartItems, setCartItems] = useState([]);

  useEffect(() => {
    const loadCart = async () => {
      const cart = await AsyncStorage.getItem('cart');
      if (cart) {
        setCartItems(JSON.parse(cart));
      }
    };
    loadCart();
  }, []);

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

  return (
    <View style={styles.container}>
      <FlatList
        data={cartItems}
        renderItem={renderItem}
        keyExtractor={item => item.id.toString()}
      />
      <Button title="Checkout" onPress={() => {/* Checkout logic */}} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  item: {
    padding: 20,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc',
  },
  title: {
    fontSize: 18,
  },
  price: {
    fontSize: 16,
    color: 'green',
  },
});

export default CartScreen;
// screens/ProductDetailsScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';

const ProductDetailsScreen = ({ route, navigation }) => {
  const { product } = route.params;

  const addToCart = async () => {
    const cart = await AsyncStorage.getItem('cart');
    let cartItems = cart ? JSON.parse(cart) : [];
    cartItems.push(product);
    await AsyncStorage.setItem('cart', JSON.stringify(cartItems));
    alert('Item added to cart');
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{product.title}</Text>
      <Text style={styles.description}>{product.description}</Text>
      <Text style={styles.price}>${product.price}</Text>
      <Button title="Add to Cart" onPress={addToCart} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
  },
  description: {
    fontSize: 16,
    marginVertical: 10,
  },
  price: {
    fontSize: 20,
    color: 'green',
    marginVertical: 10,
  },
});

export default ProductDetailsScreen;

  1. Final Touches and Testing

Step 1: Test the Application

Run the application on your emulator or physical device:

npx react-native run-android
# or
npx react-native run-ios

Step 2: Verify Functionality

  • Ensure you can navigate between the product list and product details screens.
  • Verify that products can be added to the cart and that the cart persists between app restarts.

Conclusion

In this project, you have built a simple e-commerce application using React Native. You have learned how to:

  • Set up navigation between different screens.
  • Fetch and display data from an API.
  • Handle user actions and manage state.
  • Persist data using AsyncStorage.

This project has provided a comprehensive overview of how to build a real-world application with React Native, integrating various concepts and techniques. Continue to explore and enhance this application by adding more features, such as user authentication, payment integration, and more.

© Copyright 2024. All rights reserved