Day 4: Implementing a Shopping Cart with Local Storage


Today, you’ll implement a shopping cart for your e-commerce app. The shopping cart will allow users to add products and view their selected items. You’ll use AsyncStorage for persistent storage, enabling users to retain their cart items even if they close the app.

What You Will Do Today:

  1. Set up AsyncStorage to save cart items.
  2. Create a shopping cart context to manage cart state globally.
  3. Implement functions to add, view, and remove items from the cart.

Step 1: Installing AsyncStorage

  1. Install the @react-native-async-storage/async-storage package:
   npm install @react-native-async-storage/async-storage
  1. Import AsyncStorage in your app where necessary.

Step 2: Setting Up Cart Context for Global State Management

  1. In the src folder, create a new folder called context and add a file named CartContext.js.
   // src/context/CartContext.js
   import React, { createContext, useState, useEffect } from 'react';
   import AsyncStorage from '@react-native-async-storage/async-storage';

   export const CartContext = createContext();

   export const CartProvider = ({ children }) => {
     const [cart, setCart] = useState([]);

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

     const saveCart = async (updatedCart) => {
       setCart(updatedCart);
       await AsyncStorage.setItem('cart', JSON.stringify(updatedCart));
     };

     const addToCart = (product) => {
       const updatedCart = [...cart, product];
       saveCart(updatedCart);
     };

     const removeFromCart = (productId) => {
       const updatedCart = cart.filter((item) => item.id !== productId);
       saveCart(updatedCart);
     };

     return (
       <CartContext.Provider value={{ cart, addToCart, removeFromCart }}>
         {children}
       </CartContext.Provider>
     );
   };

Explanation of Code:

  • CartContext: Provides global access to the cart.
  • addToCart and removeFromCart: Functions to add and remove items in the cart.
  • AsyncStorage: Persists cart data, so it’s saved even if the app is closed.
  1. Wrap the App.js component with CartProvider to provide cart data to all screens.
   // App.js
   import React from 'react';
   import { NavigationContainer } from '@react-navigation/native';
   import { createStackNavigator } from '@react-navigation/stack';
   import LoginScreen from './screens/LoginScreen';
   import ProductList from './screens/ProductList';
   import ProductDetail from './screens/ProductDetail';
   import { CartProvider } from './context/CartContext';

   const Stack = createStackNavigator();

   export default function App() {
     return (
       <CartProvider>
         <NavigationContainer>
           <Stack.Navigator>
             <Stack.Screen name="LoginScreen" component={LoginScreen} options={{ title: 'Login' }} />
             <Stack.Screen name="ProductList" component={ProductList} options={{ title: 'Products' }} />
             <Stack.Screen name="ProductDetail" component={ProductDetail} options={{ title: 'Product Details' }} />
           </Stack.Navigator>
         </NavigationContainer>
       </CartProvider>
     );
   }

Step 3: Adding “Add to Cart” Functionality on Product Detail Page

  1. In ProductDetail.js, add a button to allow users to add items to the cart.
   // screens/ProductDetail.js
   import React, { useContext } from 'react';
   import { View, Text, Button, StyleSheet } from 'react-native';
   import { CartContext } from '../context/CartContext';
   import firestore from '@react-native-firebase/firestore';

   function ProductDetail({ route }) {
     const { productId } = route.params;
     const [product, setProduct] = useState(null);
     const { addToCart } = useContext(CartContext);

     useEffect(() => {
       const fetchProduct = async () => {
         const doc = await firestore().collection('products').doc(productId).get();
         if (doc.exists) setProduct({ id: doc.id, ...doc.data() });
       };
       fetchProduct();
     }, [productId]);

     if (!product) {
       return (
         <View style={styles.container}>
           <Text>Loading...</Text>
         </View>
       );
     }

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

   const styles = StyleSheet.create({
     container: {
       flex: 1,
       padding: 16,
     },
     productName: {
       fontSize: 24,
       fontWeight: 'bold',
       marginBottom: 8,
     },
     productPrice: {
       fontSize: 20,
       color: '#888',
       marginBottom: 8,
     },
     productDescription: {
       fontSize: 16,
       color: '#555',
     },
   });

   export default ProductDetail;

Step 4: Creating a Cart Screen

  1. In the screens folder, create CartScreen.js to display cart items.
   // screens/CartScreen.js
   import React, { useContext } from 'react';
   import { View, Text, FlatList, Button, StyleSheet } from 'react-native';
   import { CartContext } from '../context/CartContext';

   function CartScreen() {
     const { cart, removeFromCart } = useContext(CartContext);

     const renderItem = ({ item }) => (
       <View style={styles.cartItem}>
         <Text style={styles.cartItemText}>{item.name}</Text>
         <Text style={styles.cartItemPrice}>${item.price.toFixed(2)}</Text>
         <Button title="Remove" onPress={() => removeFromCart(item.id)} />
       </View>
     );

     return (
       <View style={styles.container}>
         <Text style={styles.title}>Your Cart</Text>
         <FlatList
           data={cart}
           renderItem={renderItem}
           keyExtractor={(item) => item.id}
         />
       </View>
     );
   }

   const styles = StyleSheet.create({
     container: {
       flex: 1,
       padding: 16,
     },
     title: {
       fontSize: 24,
       fontWeight: 'bold',
       marginBottom: 16,
     },
     cartItem: {
       padding: 16,
       marginVertical: 8,
       backgroundColor: '#f9f9f9',
       borderRadius: 8,
       borderWidth: 1,
       borderColor: '#ddd',
     },
     cartItemText: {
       fontSize: 18,
     },
     cartItemPrice: {
       fontSize: 16,
       color: '#888',
     },
   });

   export default CartScreen;
  1. Add the CartScreen to the navigation stack in App.js:
   // App.js
   import CartScreen from './screens/CartScreen';

   // Add CartScreen to the Stack.Navigator
   <Stack.Screen name="CartScreen" component={CartScreen} options={{ title: 'Cart' }} />
  1. Add a button in ProductList to navigate to the Cart Screen:
   // screens/ProductList.js
   <Button title="View Cart" onPress={() => navigation.navigate('CartScreen')} />

Summary

Today, you implemented a shopping cart for your app using AsyncStorage for persistent data. Users can now add items to the cart, view their selected products, and remove them if needed.

See also  Laravel Pulse: Comprehensive Guide to APM

Tomorrow, you’ll set up a payment gateway to enable in-app purchases for the selected items.


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.