/ Gists / useState vs useReducer vs mySolution
On gists

useState vs useReducer vs mySolution

React

useState.jsx Raw #

import { useState } from "react";

function Cart() {
  const [cart, setCart] = useState({
    items: [],
    total: 0,
    discount: null,
    isLoading: false,
  });

  const addItem = (item) =>
    setCart(prev => ({
      ...prev,
      items: [...prev.items, item],
      total: prev.total + item.price,
    }));

  const removeItem = (id) =>
    setCart(prev => {
      const item = prev.items.find(i => i.id === id);
      return {
        ...prev,
        items: prev.items.filter(i => i.id !== id),
        total: prev.total - (item?.price || 0),
      };
    });

  const applyDiscount = (code) =>
    setCart(prev => ({ ...prev, discount: code }));

  const resetCart = () =>
    setCart({ items: [], total: 0, discount: null, isLoading: false });

  return <div>{JSON.stringify(cart)}</div>;
}

useReducer.jsx Raw #

import { useReducer } from "react";

const initialState = {
  items: [],
  total: 0,
  discount: null,
  isLoading: false,
};

function reducer(state, action) {
  switch (action.type) {
    case "addItem":
      return {
        ...state,
        items: [...state.items, action.payload],
        total: state.total + action.payload.price,
      };
    case "removeItem":
      const item = state.items.find(i => i.id === action.payload);
      return {
        ...state,
        items: state.items.filter(i => i.id !== action.payload),
        total: state.total - (item?.price || 0),
      };
    case "applyDiscount":
      return { ...state, discount: action.payload };
    case "reset":
      return initialState;
    default:
      return state;
  }
}

function Cart() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      {JSON.stringify(state)}
      <button onClick={() => dispatch({ type: "addItem", payload: { id:1, price:10 } })}>Add</button>
      <button onClick={() => dispatch({ type: "removeItem", payload: 1 })}>Remove</button>
      <button onClick={() => dispatch({ type: "applyDiscount", payload: "SUMMER10" })}>Discount</button>
      <button onClick={() => dispatch({ type: "reset" })}>Reset</button>
    </div>
  );
}

customObjectAkaUseState.jsx Raw #

import { useState } from "react";

function Cart() {
  const [cart, setCart] = useState({
    items: [],
    total: 0,
    discount: null,
    isLoading: false,
  });

  const actions = {
    addItem: (item) => setCart(prev => ({
      ...prev,
      items: [...prev.items, item],
      total: prev.total + item.price,
    })),
    removeItem: (id) => setCart(prev => {
      const item = prev.items.find(i => i.id === id);
      return {
        ...prev,
        items: prev.items.filter(i => i.id !== id),
        total: prev.total - (item?.price || 0),
      };
    }),
    applyDiscount: (code) => setCart(prev => ({ ...prev, discount: code })),
    reset: () => setCart({ items: [], total: 0, discount: null, isLoading: false }),
  };

  return (
    <div>
      {JSON.stringify(cart)}
      <button onClick={() => actions.addItem({ id:1, price:10 })}>Add</button>
      <button onClick={() => actions.removeItem(1)}>Remove</button>
      <button onClick={() => actions.applyDiscount("SUMMER10")}>Discount</button>
      <button onClick={() => actions.reset()}>Reset</button>
    </div>
  );
}