
React Native Expo Tutorial #7 | Ecommerce App - Cart Screen
We build cart screen and edited a few related component and screens.

You can also watch the YouTube video:
React Native Expo Tutorial #7 | Ecommerce App - Cart Screen
Installing Required Dependencies
yarn add zustand
Creating Cart Store
Create cartStore.ts
in store
folder:
import { create } from "zustand";
export const useCart = create((set) => ({
items: [],
addItem: (product: any) => {
set((state: any) => {
const isAddedBefore = state.items.find(
(item: any) => item.product.id === product.id
);
if (isAddedBefore) {
const index = state.items.findIndex(
(item: any) => item.product.id === isAddedBefore.product.id
);
state.items[index] = {
product: isAddedBefore.product,
quantity: isAddedBefore.quantity + 1,
};
return {
items: [...state.items],
};
} else {
return { items: [...state.items, { product, quantity: 1 }] };
}
});
},
emptyCart: () => set({ items: [] }),
}));
Editing Cart Screen
Edit cart.tsx
in app/(tabs)
component:
import { Button, ButtonText } from "@/components/ui/button";
import { HStack } from "@/components/ui/hstack";
import { Image } from "@/components/ui/image";
import { Text } from "@/components/ui/text";
import { VStack } from "@/components/ui/vstack";
import { useCart } from "@/store/cartStore";
import { FlatList } from "react-native";
const CartScreen = () => {
const items = useCart((state: any) => state.items);
const emptyCart = useCart((state: any) => state.emptyCart);
return (
<FlatList
contentContainerClassName="gap-2 p-2"
data={items}
renderItem={({ item }) => (
<HStack className="bg-white p-3" space="md">
<Image
source={item.product.image}
alt={`${item.product.title} image`}
/>
<VStack space="sm">
<Text bold>
{item.quantity > 1 ? `${item.quantity}x ` : undefined}
{item.product.title.length > 38
? item.product.title.slice(0, 38) + "..."
: item.product.title}
</Text>
<Text bold>
$
{item.quantity > 1
? item.product.price * item.quantity
: item.product.price}{" "}
USD
</Text>
</VStack>
<Text className="ml-auto">{item.product.quantity}</Text>
</HStack>
)}
ListFooterComponent={() => {
if (items.length > 0) {
return (
<Button className="bg-blue-500" onPress={() => emptyCart()}>
<ButtonText>Checkout</ButtonText>
</Button>
);
}
}}
/>
);
};
export default CartScreen;
Editing Product Details Screen
Edit [id].tsx
in app/product
component:
import { Card } from "@/components/ui/card";
import { Stack, useLocalSearchParams } from "expo-router";
import { Image } from "@/components/ui/image";
import { Text } from "@/components/ui/text";
import { VStack } from "@/components/ui/vstack";
import { Heading } from "@/components/ui/heading";
import { Box } from "@/components/ui/box";
import { Button, ButtonText } from "@/components/ui/button";
import { products } from "@/utils/lib";
import {
Toast,
ToastDescription,
ToastTitle,
useToast,
} from "@/components/ui/toast";
import { useState } from "react";
import { useCart } from "@/store/cartStore";
const ProductDetailsScreen = () => {
const { id } = useLocalSearchParams();
const addItem = useCart((state: any) => state.addItem);
const productById = products.find((product) => String(product.id) === id);
const toast = useToast();
const [toastId, setToastId] = useState(0);
const handleToast = (product: any) => {
if (!toast.isActive(String(toastId))) {
showNewToast(product);
}
};
const showNewToast = (product: any) => {
addItem(product);
const newId = Math.random();
setToastId(newId);
toast.show({
id: String(newId),
placement: "top",
duration: 4000,
render: ({ id }) => {
const uniqueToastId = "toast-" + id;
return (
<Toast
nativeID={uniqueToastId}
action="success"
variant="solid"
className="mt-8"
>
<ToastTitle>Item added to your cart!</ToastTitle>
<ToastDescription>
The item has been added to your cart!
</ToastDescription>
</Toast>
);
},
});
};
if (!productById) {
return (
<>
<Card className="flex-1 p-4">
<Heading size="3xl" className="text-red-500">
Product not found!
</Heading>
</Card>
</>
);
}
return (
<>
<Stack.Screen options={{ title: productById.title }} />
<Card className="p-5 rounded-lg flex-1">
<Image
source={{
uri: productById.image,
}}
className="mb-6 h-[240px] w-full rounded-md"
alt="image"
resizeMode="contain"
/>
<Text className="text-sm font-normal mb-2 text-typography-700 capitalize">
{productById.category}
</Text>
<VStack className="mb-6">
<Heading size="md" className="mb-4">
{productById.title}
</Heading>
<Text size="sm">{productById.description}</Text>
</VStack>
<Box className="flex-col sm:flex-row">
<Button
className="px-4 py-2 mr-0 mb-3 sm:mr-3 sm:mb-0 sm:flex-1 bg-blue-500"
onPress={() => handleToast(productById)}
>
<ButtonText size="sm">Add to cart</ButtonText>
</Button>
</Box>
</Card>
</>
);
};
export default ProductDetailsScreen;
That's it for this tutorial, we build cart screen and edited a few related component and screens.
0
0