CodeBlanks Logo Icon CodeBlanks

Cart

Write cart management with Context.

Cart Context

The cart is shared data reached from several screens. So we keep its state in a Context, not as a prop. createContext() creates a context; Provider spreads the value.

The Provider gives the cart array and an addToCart function as its value. Every screen reaches it with useContext; we can update the cart without prop drilling.

CartProvider

CartProvider is a component that defines the cart state and the addToCart function. It spreads them to children with <CartContext.Provider value={{ cart, addToCart }}>; the children prop is placed inside the Provider.

addToCart appends the new product: setCart([...cart, item]). Wrapping App with the Provider lets every child component reach the cart. So both the list and the detail can update the cart without prop drilling.

Practice Add CartContext and CartProvider

Add a CartContext and a CartProvider. Inside the Provider use const [cart, setCart] = useState([]) and an addToCart function; use <CartContext.Provider value={{ cart, addToCart }}>.

Starter code

App.js
import React, { createContext, useContext, useState } from 'react';
import { FlatList, Text, View } from 'react-native';

const products = [
  { id: '1', name: 'Pen', price: 20 },
  { id: '2', name: 'Notebook', price: 35 },
]

// Add CartContext and CartProvider here

export default function App() {
  const [selectedId, setSelectedId] = useState(null);
  const selected = products.find((p) => p.id === selectedId);
  if (selected) {
    return (
      <View>
        <Text>{selected.name}</Text>
        <Text onPress={() => setSelectedId(null)}>Back</Text>
      </View>
    );
  }
  return (
    <View>
      <Text>Store</Text>
      <FlatList
        data={products}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <Text onPress={() => setSelectedId(item.id)}>{item.name}</Text>
        )}
      />
    </View>
  );
}

Sample solution

App.js
import React, { createContext, useContext, useState } from 'react';
import { FlatList, Text, View } from 'react-native';

const products = [
  { id: '1', name: 'Pen', price: 20 },
  { id: '2', name: 'Notebook', price: 35 },
]

const CartContext = createContext();

function CartProvider({ children }) {
  const [cart, setCart] = useState([]);
  const addToCart = (item) => setCart([...cart, item]);
  return (
    <CartContext.Provider value={{ cart, addToCart }}>
      {children}
    </CartContext.Provider>
  );
}

export default function App() {
  const [selectedId, setSelectedId] = useState(null);
  const selected = products.find((p) => p.id === selectedId);
  if (selected) {
    return (
      <View>
        <Text>{selected.name}</Text>
        <Text onPress={() => setSelectedId(null)}>Back</Text>
      </View>
    );
  }
  return (
    <View>
      <Text>Store</Text>
      <FlatList
        data={products}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <Text onPress={() => setSelectedId(item.id)}>{item.name}</Text>
        )}
      />
    </View>
  );
}

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What should the CartProvider value contain?

  • Only styles
  • Only the product array
  • Only navigation
  • cart and addToCart Correct answer

Explanation: The Provider should spread the cart array and the addToCart function.

2 Write the addToCart body

Question
const addToCart = (item) => setCart([...cart, ____]);
Answer
const addToCart = (item) => setCart([...cart, item]);

Explanation: The new product is added as item.

3 Match the cart concepts

Term Meaning
createContext Creates context
Provider Spreads value
cart Cart array
addToCart Adds product

All lessons in Intermediate