Back
Syntax
Study
Editor
Mode:
HTML
CSS
JavaScript
PHP
Reset
Run »
HTML / CSS / JS
import { createContext, useContext, useReducer } from 'react'; // ── Reducer ──────────────────────────────────────────────────────────────── function cartReducer(state, action) { switch (action.type) { case 'ADD_ITEM': return { ...state, items: [...state.items, action.item] }; case 'REMOVE_ITEM': return { ...state, items: state.items.filter(i => i.id !== action.id) }; case 'CLEAR': return { ...state, items: [] }; default: throw new Error(`Unknown action: ${action.type}`); } } // ── Two contexts: state + dispatch ───────────────────────────────────────── const CartStateContext = createContext(null); const CartDispatchContext = createContext(null); export function CartProvider({ children }) { const [state, dispatch] = useReducer(cartReducer, { items: [] }); return ( <CartStateContext.Provider value={state}> <CartDispatchContext.Provider value={dispatch}> {children} </CartDispatchContext.Provider> </CartStateContext.Provider> ); } export const useCartState = () => useContext(CartStateContext); export const useCartDispatch = () => useContext(CartDispatchContext); // ── Consumer ─────────────────────────────────────────────────────────────── function CartBadge() { const { items } = useCartState(); // re-renders on state change return <span>{items.length}</span>; } function AddToCartButton({ product }) { const dispatch = useCartDispatch(); // stable – never re-renders return ( <button onClick={() => dispatch({ type: 'ADD_ITEM', item: product })}> Add to cart </button> ); }
Result
Open