Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

For a small cart shared within one part of an app, React Context may be enough. For a more convention-driven, centralized workflow, consider Redux Toolkit; for a store-oriented API without a required app-wide provider, consider Zustand; and for state composed from atoms and derived relationships, consider Jotai. None is a universal performance winner: choose by state model, update flow, subscription needs, and team fit—not an unverified benchmark ranking.

Here, all four examples use the same cart shape and behavior: adding an existing product increases its quantity; removing a product deletes it; setting quantity to zero or less removes it; and the displayed item count is the sum of quantities. The subtotal is the sum of unit price multiplied by quantity.

What changes between the four approaches?

Approach Where state lives How updates are expressed Useful distinction
Context A value provided to a React subtree Usually component state or a reducer, with consumers dispatching updates Built into React; components reading a changed context value update. It is value passing, not by itself a selector-based state-management framework. React createContext and useContext
Redux Toolkit A Redux store Dispatch actions handled by slice reducers; components select data The Redux team’s recommended approach for writing Redux logic, with conventions and helpers for common Redux tasks. Redux Getting Started and Redux Toolkit Usage Guide
Zustand A store created with Zustand Call store actions; components select the state they use Store-oriented setup without a required app-wide context-provider wrapper. Zustand comparison
Jotai Atoms and their dependency relationships Read, derive, or write atoms An atomic, bottom-up model, contrasted in its documentation with Zustand’s single-object, top-down store model. Jotai comparison

The code below is illustrative implementation code, not a measured comparison. Each example uses the same starting cart: two notebooks at 4.50 each. The example product added is one pen at 1.25. A count of three and subtotal of 10.25 would result after adding the pen; changing the notebooks to quantity one would then make the count two and subtotal 5.75. These values describe the example’s arithmetic, not benchmark results.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Context: share a reducer-backed value through a subtree

Context is a good fit when the cart naturally belongs to a particular subtree and the state and update behavior remain manageable there. Keep the update logic in a reducer so that add, remove, and quantity changes have one defined implementation.

#1 Best Overall
Sale
Tera Barcode Scanner Wireless 1D Laser Cordless Barcode Reader with Battery Level Indicator, Versatile 2 in 1 2.4Ghz Wireless and USB 2.0 Wired
  • Larger battery enables longer continuous usage and twice the stand-by time. With the unique battery indicator light showing the remaining battery level, no more Low Battery Anxiety.
  • The curved handle is extended and widened. With specially designed smooth and flat trigger for a better grip.
  • The orange anti shock silicone protective cover can prevent scratches and friction even when dropped from up to 6.56 feet. IP54 technology protects the wireless barcode scanner from dust.
  • Plug and play with the USB receiver or the USB cable, no driver installation needed. Easy and quick to set up. Wireless transmission distance reaches up to 328 ft. in barrier free environment.
  • Supports almost all 1D Barcodes: Febraban Bank Code, Codabar, Code 11, Code93, MSI, Code 128, EAN-128, Code 39, EAN-8, EAN-13, UPC-A, ISBN, Industrial 25, Interleaved 25, Standard 25, Matrix. Reads damaged, fuzzy, reflective and smudged barcodes.
import { createContext, useContext, useMemo, useReducer } from 'react';

const initialItems = [
  { productId: 'notebook', name: 'Notebook', unitPrice: 4.5, quantity: 2 },
];

function cartReducer(items, action) {
  switch (action.type) {
    case 'add': {
      const existing = items.find(item => item.productId === action.item.productId);
      return existing
        ? items.map(item => item.productId === action.item.productId
            ? { ...item, quantity: item.quantity + action.item.quantity }
            : item)
        : [...items, action.item];
    }
    case 'remove':
      return items.filter(item => item.productId !== action.productId);
    case 'setQuantity':
      return action.quantity <= 0
        ? items.filter(item => item.productId !== action.productId)
        : items.map(item => item.productId === action.productId
            ? { ...item, quantity: action.quantity }
            : item);
    default:
      return items;
  }
}

const CartContext = createContext(null);

export function CartProvider({ children }) {
  const [items, dispatch] = useReducer(cartReducer, initialItems);
  const value = useMemo(() => ({ items, dispatch }), [items]);
  return <CartContext value={value}>{children}</CartContext>;
}

function CartSummary() {
  const cart = useContext(CartContext);
  if (!cart) throw new Error('CartSummary must be inside CartProvider');
  const itemCount = cart.items.reduce((sum, item) => sum + item.quantity, 0);
  const subtotal = cart.items.reduce(
    (sum, item) => sum + item.unitPrice * item.quantity, 0,
  );
  return <p>{itemCount} items — ${subtotal.toFixed(2)}</p>;
}

function AddPenButton() {
  const { dispatch } = useContext(CartContext);
  return <button onClick={() => dispatch({
    type: 'add',
    item: { productId: 'pen', name: 'Pen', unitPrice: 1.25, quantity: 1 },
  })}>Add pen</button>;
}

In React 19, the context object itself can be used as the provider, as shown. In earlier React versions, write <CartContext.Provider value={value}>. Components that read a context update when its provided value changes. If a single context holds the whole cart and changes on every cart update, all consumers of that context are subscribed to that changing value; this does not mean every descendant that does not read it automatically updates because of Context.

Redux Toolkit: centralize updates in a store and slice

Redux Toolkit suits teams that want explicit action and reducer conventions around a shared store. The slice defines cart updates; the summary selects and derives only the values it displays. The application is wrapped in Redux’s Provider so React components can access the store.

Rank #2
Sale
Tera Barcode Scanner Wireless with Screen: Pro Version 1D 2D QR with Setting Keypad Charging Cradle Works with Bluetooth 2.4G Wireless USB Wired Handheld Bar Code Reader HW0009
  • 【Unique Designed Screen Setting】It allows you to customize the screen display according to your preferences. With this innovative feature, you can easily set the language, adjust volume settings, select connection options, and view stored and total barcodes. Experience unparalleled convenience and flexibility as you personalize the settings of your Tera HW0009 to suit your specific needs. 【Package Includes: Barcode Scanner x1, Charging Cradle x1, Charging Cable x1, User Manual x1】
  • 【Superior Global CMOS Imaging Scanning】This advanced scanner excels in fast and accurate reading of both ordinary and high-density barcodes, including challenging formats like PDF417 found on driver's licenses. Its exceptional performance effortlessly handles various scanning scenarios, including underwater scanning, reading barcodes on silver paper, reflective materials, and more.
  • 【Charging Cradle & 2500mAh Large Battery】Designed with a convenient charging cradle, the HW0009 barcode scanner allows you to easily charge it whenever it's not in use. In addition, the scanner itself is equipped with a powerful 2500mAh battery, ensuring seamless all-day operation without the need for frequent charging.
  • 【3-in-1 Connections & Widely Compatible】 Tera HW0009 wireless barcode scanner can work with bluetooth & 2.4G wireless & usb wired. The transmission distance can be 328ft in barrier free environment and 114ft in obstacles environment using 2.4G USB dongle. It can be connected with a variety of devices, such as smartphones, computers, POS, tablets. In addition, it is also compatible with various operating systems, such as windows 11/10/8/7/xp, Mac OS, iOS, android, linux.
  • 【1D 2D QR code Programmable】2D: QR code, Data Matrix, PDF417(including PDF417 on driver’s license), Aztec, Maxicode, Micro QR, Micro PDF417; 1D: UPC/EAN, Code 128/EAN128, GS1-128, ISBT-128, Standard 2 of 5, Matrix 2 of 5, Code 39, Code 32, Code 93, Code 11, Codabar, PLESSEY, MSI, GSI Databar, ITF-14, GS1.
import { configureStore, createSlice } from '@reduxjs/toolkit';
import { Provider, useDispatch, useSelector } from 'react-redux';

const initialItems = [
  { productId: 'notebook', name: 'Notebook', unitPrice: 4.5, quantity: 2 },
];

const cartSlice = createSlice({
  name: 'cart',
  initialState: { items: initialItems },
  reducers: {
    addItem(state, action) {
      const added = action.payload;
      const existing = state.items.find(item => item.productId === added.productId);
      if (existing) existing.quantity += added.quantity;
      else state.items.push(added);
    },
    removeItem(state, action) {
      state.items = state.items.filter(item => item.productId !== action.payload);
    },
    setQuantity(state, action) {
      const { productId, quantity } = action.payload;
      if (quantity <= 0) {
        state.items = state.items.filter(item => item.productId !== productId);
      } else {
        const item = state.items.find(item => item.productId === productId);
        if (item) item.quantity = quantity;
      }
    },
  },
});

const store = configureStore({ reducer: { cart: cartSlice.reducer } });
const { addItem, removeItem, setQuantity } = cartSlice.actions;

export function CartApp({ children }) {
  return <Provider store={store}>{children}</Provider>;
}

function CartSummary() {
  const items = useSelector(state => state.cart.items);
  const itemCount = items.reduce((sum, item) => sum + item.quantity, 0);
  const subtotal = items.reduce(
    (sum, item) => sum + item.unitPrice * item.quantity, 0,
  );
  return <p>{itemCount} items — ${subtotal.toFixed(2)}</p>;
}

function AddPenButton() {
  const dispatch = useDispatch();
  return <button onClick={() => dispatch(addItem({
    productId: 'pen', name: 'Pen', unitPrice: 1.25, quantity: 1,
  }))}>Add pen</button>;
}

Redux Toolkit’s reducer code can look like it mutates state, but the Toolkit’s reducer setup uses immutable update logic under the hood. The trade-off is more explicit structure: a store, slice, actions, dispatching, and selectors. Those conventions can support predictable team workflows, but are additional concepts compared with a local reducer or a small store.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Zustand: keep cart state and actions in a store

Zustand places the data and update functions together in a store. Components subscribe through selectors, so a summary can select its count and subtotal rather than taking a context value containing the entire cart object.

Rank #3
Tera Barcode Scanner with Battery Indicator: 2D Wireless, D5100 Orange
  • 【Battery Level Indicator and 2200mAh Capacity】Larger battery enables longer continuous usage and twice the stand-by time of others. With the unique battery indicator light showing the remaining battery level, no more Low Battery Anxiety.
  • 【Ergonomic Design】 The curved handle is extended and thickened, tailor-made for North America customers. Specially designed smooth and flat trigger for better grip. 【Package Includes】Barcode Scanner x1, USB Cable x1, Dongle x1, User Manual x1.
  • 【Anti-Shock Silicone】 The orange anti-shock silicone protective cover can avoid scratches and friction while falling from the height of 6.56 feet. IP54 technology protects the wireless barcode scanner from dust.
  • 【2.4 GHz Wireless plus USB 2.0 Wired Connection】 Plug and play with the USB receiver or the USB cable, no driver installation needed. Easy and quick to set up. Wireless transmission distance reaches up to 328 ft. in barrier free environment.
  • 【Digital and Printed 1D 2D QR Bar Code Symbologies】1D: Codabar, Code 11, Code93, MSI, Code 128, UCC/EAN-128, Code 39, EAN-8, EAN-13, UPC-A, ISBN, Industrial 25, Interleaved 25, Standard25, Matrix 2D: QR, DataMatrix, Aztec, Hanxin, Micro PDF417. (Note: Not compatible with Square.)
import { create } from 'zustand';

const useCartStore = create((set) => ({
  items: [
    { productId: 'notebook', name: 'Notebook', unitPrice: 4.5, quantity: 2 },
  ],
  addItem: (added) => set(state => {
    const existing = state.items.find(item => item.productId === added.productId);
    return {
      items: existing
        ? state.items.map(item => item.productId === added.productId
            ? { ...item, quantity: item.quantity + added.quantity }
            : item)
        : [...state.items, added],
    };
  }),
  removeItem: (productId) => set(state => ({
    items: state.items.filter(item => item.productId !== productId),
  })),
  setQuantity: (productId, quantity) => set(state => ({
    items: quantity <= 0
      ? state.items.filter(item => item.productId !== productId)
      : state.items.map(item => item.productId === productId
          ? { ...item, quantity }
          : item),
  })),
}));

function CartSummary() {
  const itemCount = useCartStore(state =>
    state.items.reduce((sum, item) => sum + item.quantity, 0),
  );
  const subtotal = useCartStore(state =>
    state.items.reduce((sum, item) => sum + item.unitPrice * item.quantity, 0),
  );
  return <p>{itemCount} items — ${subtotal.toFixed(2)}</p>;
}

function AddPenButton() {
  const addItem = useCartStore(state => state.addItem);
  return <button onClick={() => addItem({
    productId: 'pen', name: 'Pen', unitPrice: 1.25, quantity: 1,
  })}>Add pen</button>;
}

This example calculates derived values in the subscribing component’s selectors. For a larger app, consider where to define reusable selectors and how to scope or test stores. The documented setup distinction is that Zustand does not require the app-wide context-provider wrapper used for Redux integration; that alone does not establish a speed or bundle-size advantage.

Jotai: build the cart from atoms and derived values

Jotai models state as atoms, which can be composed through dependencies. This example uses one atom for the cart array, two read-only derived atoms for the displayed values, and write atoms for the three operations. That is one possible boundary choice, not a rule that each cart field needs its own atom.

Rank #4
Zebra Symbol DS2278-SR Wireless 2D/1D Bluetooth Barcode Scanner
  • The kit comes with one barcode scanner, one cradle, one battery, one USB cable and manual.
  • Eliminate Bluetooth Interference with Zebra’s Proprietary Wi-Fi Friendly Mode------Ensure that your wireless DS2278 Bluetooth imagers only operate on channels that are not shared with your WLAN, protecting WLAN service levels for your workers and your customers.
  • Unsurpassed Scanning Range------Workers can scan barcodes across a wide range (0.5 in./1.23 cm to 14.5 in./36.8 cm), improving checkout speed and reducing training time.
  • Pre-configured and Ready to Use, Right Out of the Box------Since the default settings are optimized for the majority of scanning applications, you can use the DS2278-SR imager the moment you take it out of the box — no configuration required. With omni-directional scanning, users never need to line up the imager and the barcode — unlike 1D scanners.
  • Control Your Scanners from a Smartphone, Tablet or PC------You can easily control the beeper, LED and Symbology settings; display scanned barcode data; access model and serial number information and more from Windows, Android and iOS hosts.
import { atom, useAtomValue, useSetAtom } from 'jotai';

const cartAtom = atom([
  { productId: 'notebook', name: 'Notebook', unitPrice: 4.5, quantity: 2 },
]);

const itemCountAtom = atom(get =>
  get(cartAtom).reduce((sum, item) => sum + item.quantity, 0),
);
const subtotalAtom = atom(get =>
  get(cartAtom).reduce((sum, item) => sum + item.unitPrice * item.quantity, 0),
);

const addItemAtom = atom(null, (get, set, added) => {
  const items = get(cartAtom);
  const existing = items.find(item => item.productId === added.productId);
  set(cartAtom, existing
    ? items.map(item => item.productId === added.productId
        ? { ...item, quantity: item.quantity + added.quantity }
        : item)
    : [...items, added]);
});

const removeItemAtom = atom(null, (get, set, productId) => {
  set(cartAtom, get(cartAtom).filter(item => item.productId !== productId));
});

const setQuantityAtom = atom(null, (get, set, { productId, quantity }) => {
  const items = get(cartAtom);
  set(cartAtom, quantity <= 0
    ? items.filter(item => item.productId !== productId)
    : items.map(item => item.productId === productId
        ? { ...item, quantity }
        : item));
});

function CartSummary() {
  const itemCount = useAtomValue(itemCountAtom);
  const subtotal = useAtomValue(subtotalAtom);
  return <p>{itemCount} items — ${subtotal.toFixed(2)}</p>;
}

function AddPenButton() {
  const addItem = useSetAtom(addItemAtom);
  return <button onClick={() => addItem({
    productId: 'pen', name: 'Pen', unitPrice: 1.25, quantity: 1,
  })}>Add pen</button>;
}

The derived atoms make the count and subtotal definitions reusable and keep them out of individual UI components. Atom boundaries are a design decision: model relationships that are meaningful to the app rather than splitting data mechanically.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Which one should you choose for a cart?

  • Choose Context when the cart is scoped to a subtree, sharing a value through that subtree is the main need, and the changed-context subscription behavior is appropriate.
  • Choose Redux Toolkit when the team wants Redux’s recommended conventions, centralized reducers and actions, and an explicit store workflow.
  • Choose Zustand when a store-and-actions mental model fits and you want to avoid a required app-wide provider wrapper.
  • Choose Jotai when composing state from atoms and derived dependencies maps well to the domain.

Before deciding, trace the actual UI: which components need the cart, whether they need the same data, where derived values should live, how many contributors must follow consistent update conventions, and what debugging or testing practices the team needs. Familiarity with the model is a practical factor, not a performance benchmark.

Best Value
NETUM Bluetooth Barcode Scanner, Support 2.4G Wireless & Bluetooth & Wired Connect Smart Phone, Tablet, PC, CCD Bar Code Reader Work with Windows, Mac,Android (NT-1228BC)
  • Widely Compatible: Bluetooth Barcode Scanner for iPhone iPad Android Tablet PC, Support HID / SPP / BLE mode via bluetooth, Work with Windows XP/7/8/10, Mac OS, Windows Mobile, Android OS, iOS, Linux.
  • Strong Recognition Ability: With the 2500 pixels high-resolution CCD sensor Engine, Rapidly decodes all 1D and stacked barcodes (including ISBN book), even worn, damaged or tightly spaced codes. Scan 1D codes directly from paper or screen, such as a computer monitor, smartphone, or tablet, or scan through glass surfaces, plastic shrink wrap, a CCD scanner is likely the best way to go.
  • Automatic Scanning: NT-1228bc barcode scanner have three scanning modes: manual trigger mode, continuous scanning mode and auto-sensing scanning mode. In addition, there is a storage mode. Storage mode can be used when you are out of range of Bluetooth and wireless connectivity. Supports storage of up to 100,000 barcodes. Note: Before use, you need to scan the corresponding setting barcode on the manual.
  • 2600mAh Battery Upgraded: Continuous scanning up to 200,000 times on a full charge. After a full charge the scanner can be used for one month at least, even in warehouses and at pos checkout counters where scanners are frequently used. In libraries and hospitals it can be used even longer.
  • Programmable Configuration: Add custom prefixes/ suffixes, delete characters, Add keyboard keys/ combinations (terminator TAB, CR&LF, Home etc.), Enable or disable the barcode type as you want. Buzzer can be set to mute to allow for a quiet operation.(Note: It does not work with square POS / Divalto / DoorDash / Lightspeed POS system)

What the benchmark claims do—and do not—show

A title-matched DEV Community article attributed to PrepStack reports component render counts and timings for a 1,000-component test, along with migration-related figures and categorical package-size claims. The available page does not establish enough detail about environment, implementation parity, React version, build mode, repetitions, measurement method, workload, or independent replication to treat those numbers as a general comparison.

No benchmark is presented here. Render counts depend on what is counted—component function calls, commits, parent renders, and development Strict Mode behavior can differ—and elapsed time depends on the runtime and test conditions. A useful comparison would publish identical implementations and workload, the React version and build mode, hardware, warm-up and repetition protocol, a definition of each metric, and raw results. Without that evidence, there is no substantiated basis for naming one of these four the universal performance winner.

Keep server-fetched data conceptually separate

A shopping cart often combines client-side UI state with product or inventory information fetched from a server. These are different concerns: this comparison shows how to manage the cart’s client-side items and derived display values; it does not establish which approach should own server-fetched or cached data. Avoid treating this cart example as a recommendation that a particular query library is required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.