Issue encountered while attempting to store quantity in localStorage

Currently, I am developing a shopping cart feature for my website and I would like to display the total quantity of items in the header.

I have implemented useReducer and context to manage the state of my items within the application, which is functioning correctly. However, upon page refresh, all data is lost. To address this issue, I plan to store the item quantity in localStorage.

My approach involves checking if the quantity already exists in localStorage when adding a new item to the cart. Unfortunately, I am facing an issue where the process seems to run twice, resulting in the double addition of the intended quantity.

Apologies for any grammatical errors, as English is not my first language.

import { useReducer } from "react";

import CartContext from "./cart-context";

const defaultCartState = {
  items: [],
  totalAmount: 0,
  totalQuantity: 0,
};

const cartReducer = (state, action) => {
  if (action.type === "ADD") {
    const updatedTotalAmount =
      state.totalAmount + action.item.price * action.item.amount;

    if (JSON.parse(localStorage.getItem("quantity"))) {
      state.totalQuantity = JSON.parse(localStorage.getItem("quantity"));
    }

    console.log(state.totalQuantity);
    console.log(action.item.amount);

    const updatedTotalQuantity = state.totalQuantity + action.item.amount;

    const existingCartItemIndex = state.items.findIndex(
      (item) => item.id === action.item.id
    );
    const existingCartItem = state.items[existingCartItemIndex];
    let updatedItems;

    if (existingCartItem) {
      const updatedItem = {
        ...existingCartItem,
        amount: existingCartItem.amount + action.item.amount,
      };
      updatedItems = [...state.items];
      updatedItems[existingCartItemIndex] = updatedItem;
    } else {
      updatedItems = state.items.concat(action.item);
    }

    localStorage.setItem("quantity", JSON.stringify(updatedTotalQuantity));

    return {
      items: updatedItems,
      totalAmount: updatedTotalAmount,
      totalQuantity: updatedTotalQuantity,
    };
  }

  return defaultCartState;
};

CartProvider

const CartProvider = (props) => {
  const [cartState, dispatchCartAction] = useReducer(
    cartReducer,
    defaultCartState
  );

  const addItemToCartHandler = (item) => {
    dispatchCartAction({ type: "ADD", item: item });
  };

  const removeItemFromCartHandler = (id) => {
    dispatchCartAction({ type: "REMOVE", id: id });
  };

  const cartContext = {
    items: cartState.items,
    totalAmount: cartState.totalAmount,
    totalQuantity: cartState.totalQuantity,
    addItem: addItemToCartHandler,
    removeItem: removeItemFromCartHandler,
  };

  return (
    <CartContext.Provider value={cartContext}>
      {props.children}
    </CartContext.Provider>
  );
};

export default CartProvider;

The issue with the process running twice can be observed in the console: Screenshot of console

Answer №1

When creating a context, try to set the value from local storage only once, and pass a default state like this:

import { useContext, useReducer, createContext } from 'react'

const defaultCartState = {
  items: [],
  totalAmount: 0,
  totalQuantity: JSON.parse(localStorage.getItem('quantity')) ?? 0,
}

const CartContext = createContext(defaultCartState)

const cartReducer = (state, action) => {
  // Reducer logic here
}

const CartProvider = (props) => {
  // Provider logic here
}

const My = () => {
  // Component code here
}
const App = () => {
  // App rendering logic here
}

export default App

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sentry: Easily upload source maps from a nested directory structure

I am currently developing a NextJs/ReactJs application using Typescript and I am facing an issue with uploading sourcemaps to Sentry artefacts. Unlike traditional builds, the output folder structure of this app mirrors the NextJs pages structure, creating ...

The issue with Spring's JSON serialization causing errors when converting to a Java Map

In my ReactJs client, I have a form with multiple radio inputs and one textarea input that I submit using axios. The code for the request is as follows: axios.post("/wellbeing/" + params.wellbeingSurveyType, { formAnswersJson: formAnswers }) ...

When using Material UI select inside a React datatable component, an error occurs mentioning that event.target.getAttribute is not a valid function

Recently, I started using the react-datatable-component and incorporating custom cells to enable editing for specific fields. Unfortunately, I encountered an issue while implementing the Select field from material UI. It was giving me an error stating tha ...

Encountering the "TypeError: Cannot call a class as a function" error while using EditorJS in NextJs

I am facing an issue with integrating EditorJs into my NextJs app. This is what I have tried: Editor.js import dynamic from "next/dynamic"; let CustomEditor = dynamic(() => import("./CustomEditor"), { ssr: false ...

Is it possible to leverage the flex features of react-native in a manner similar to the row/column system of

Is it a good idea to utilize flex in react native by creating custom components that retrieve flex values? I previously used the bootstrap grid system and now I am exploring react native. Is there a way to implement this example using react-native bootstr ...

How to customize the page background color in Next JS

I am currently working on a project using Next Js and have encountered an issue. I have a global.css file set up in the project, but I need to change the background color of a specific page without affecting the rest of the project. Although I have tried u ...

Building a Model Class with redux-orm and TypeScriptCreating a new Model Class with

I've been successfully using redux-orm with JavaScript, however, I'm facing issues when trying to convert my code to TypeScript. Even though I have already implemented the render() method in my Folder Model Class, the TypeScript transpiler is sh ...

Animation issue in Material UI autocomplete label feature

Hello, I am currently delving into the world of React and Material UI. I have been working on implementing the Material UI auto complete feature with chip functionality. You can see my progress here: https://codesandbox.io/s/runh6. Everything seems to be w ...

How can I include an HTML tag within a select input value in a React.js project?

I am facing an issue while trying to map values from the input field of a select tag. It seems to be returning [Object object] for some reason. When I do not include another tag in the return statement of the map function, the output works fine. However, I ...

Is it possible to incorporate AngularJS 1.4, AngularJS 2.0, and ReactJS all within the same project?

My project is a collection of tags that are referred to by different names in various languages. I refer to these elements as views. Currently, our users are creating views using Angular 1.4. I am looking to provide flexibility to our users so they can ...

Is it possible to make the clear indicator in react-select remain visible even after clearing the selection

How can I make the ClearIndicator remain visible after clearing in react-select? I have customized the selector ClearIndicator to display as a downward arrow by default, and when hovered over, it changes to a cross. However, after clicking the cross, I w ...

Parent-sourced Material Tooltip Text Display

I would like to implement a ToolTip in the following manner: const MyComponent = () => { [open, setOpen] = useState(false); return <div (onClick)={() => {setOpen(!open)}> Click to open tooltip <Tooltip text="some ...

Executing a function within JSX to dismiss a modal in NextJS

I am currently utilizing the Tanstack React Query library to perform a POST request from a Modal that includes a form: const addDay = (day: TDay) => { const apiURL = process.env.NEXT_PUBLIC_SERVER_URL const queryURL = apiURL + router ...

Tips for setting up CSRF protection in a Next.js frontend application working in conjunction with a Spring Security backend application

I have been working on a project that utilizes Next.js for the frontend and Spring Boot for the server. I am currently implementing the user login/register feature. The core functionality is working, where a user can successfully send a post login request ...

Front-end and back-end seamlessly integrated in Next.js

I am new to this area and curious about whether it's better to include an API within my project or have a separate back-end integrated. I understand that having a separate backend means paying for two hosting services, whereas incorporating it within ...

Utilize the <wbr> tag within FormattedMessage and assign it as a value while coding with TypeScript

Trying out the optional word break tag <wbr> in a message within <FormattedMessage id="some:message" />. Context Some words or texts are too lengthy for certain parent elements on smaller mobile screens, and we have a column layout t ...

Creating audio streams using react-player

I am currently working on integrating the react-player component from CookPete into my website. However, I am facing a challenge in setting up multiple audio streams. Additionally, I want to include both DASH and HLS video streams but adding them as an arr ...

What steps should I take to display a Material UI grid in React without triggering the warning about the missing unique key

In my current project, I am utilizing React and Material UI to display a grid. The grid's rows are populated from an array of data, with each row containing specific information in columns structured like this: <Grid container> {myData.map((re ...

Combining the Express.js API with React to create an interactive data visualization using CanvasJS

After developing an api in node.js that provides data in json format, I am looking to utilize this data for visualization purposes. To demonstrate this, I have prepared a sample of data visualization using canvasjs within React. class BarChart extends Com ...

Tidying up following the execution of an asynchronous function in useEffect

Recently, I've been facing a challenge while migrating a React project to TypeScript. Specifically, I'm having trouble with typing out a particular function and its corresponding useEffect. My understanding is that the registerListener function s ...