I am unable to utilize Local Storage within NextJS

type merchandiseProps = {
  merchandises: merchandiseType[];
  cart?:string,
  collection?:string,
  fallbackData?: any
};

const MerchandiseList: FC<merchandiseProps> = ({ merchandises }) => {
  const [cart, setCart] = useState<merchandiseType[]>(
    typeof window !== undefined ? JSON.parse(localStorage.getItem("collection") || "[]") : ''
  );
  const [wishlist, setWishlist] = useState<merchandiseType[]>(
    JSON.parse(localStorage.getItem("collection") || "[]")
  );

  useEffect(() => {
    localStorage.setItem("cart", JSON.stringify(cart));
    localStorage.setItem("collection", JSON.stringify(wishlist));
  }, [cart, wishlist]);

  const addToCart = (item: merchandiseType) => {
    setCart([...cart, item]);
  };

  const addToCollection = (item: merchandiseType) => {
    setWishlist([...wishlist, item]);
  }; 

I'm trying to use typeof window but facing issues. Seeking assistance..................

Answer №1

Apparently, the usage of Next's SSR or SSG on your website is causing the (pre-)rendering of pages on the server where window is not defined, as you mentioned.

The problem lies in the following code snippet:

 const [cart, setCart] = useState<productsType[]>(
    typeof window !== undefined ? JSON.parse(localStorage.getItem("wishlist") || "[]") : ''
  );

On the server side, the variable cart will be initialized as an empty string, while on the client side during React Hydration, it will fetch the value from localStorage, leading to a content-mismatch error during hydration.

If you are encountering the error message:

Hydration failed because the initial UI does not match what was rendered on the server.

Solution

To resolve this issue, initialize the state inside a useEffect that only runs on the client side, like so:

 const [cart, setCart] = useState<productsType[]>([])

  useEffect(() => {
    if (cart.length) return;
    
    const localVal = JSON.parse(localStorage.getItem("wishlist") || "[]")

    if (Array.isArray(localVal) && localVal.length){
       setCart(localVal)   
    }

  }, []);

If you wish to synchronize localStorage with the state, you can use the following approach instead:

 const [cart, setCart] = useState<productsType[]>([])

  useEffect(() => {
    if (cart.length){
       localStorage.setItem("cart", JSON.stringify(cart));
       return;
    }

    const localVal = JSON.parse(localStorage.getItem("wishlist") || "[]")

    if (Array.isArray(localVal) && localVal.length){
       setCart(localVal)   
    }

  }, [cart]);

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

Exploring Several Images and Videos in Angular

I'm experiencing a challenge with displaying multiple images and videos in my Angular application. To differentiate between the two types of files, I use the "format" variable. Check out Stackblitz export class AppComponent { urls; format; on ...

Discovering active path while utilizing dynamic routes - here's how!

Whenever I click on the project element in my HeadlessCMS with the URL /projects/slug-name, the projects button in my Navbar (LinkItem) does not highlight with a background color (bgColor). How can I modify this line of code: const active = path === href / ...

Using Angular, a function can be called recursively directly from within the HTML

I'm struggling with loading an image because the method getUserProfileImage() is getting triggered multiple times within a loop. Is there a way to ensure the method is only called once during each iteration? I understand that this issue is related to ...

Can dot env be utilized with next export functionality?

Is it feasible to utilize dot-env with next export in a NextJS app that has a NodeJS backend implemented as an Azure function? The NextJS app is statically exported. ...

Navigating back using the 'Back' button for modals with dynamic search parameters in a Next.js application router

Currently, I am working on a feature within a Next.js application where there is a modal accessible through a parallel route. This modal consists of tabs that can adjust the searchParams in the URL as users interact with them. The modal can be triggered by ...

Stopping event propagation does not function properly when using the Ant Design Dropdown Menu

Within my card component, I have included a Next.js Link that contains the body and footer of the card. The cardFooter section consists of an Ant Design DropDown menu with two items - Share and Report. Despite implementing preventDefault and stopPropagatio ...

Lack of MaterialUI Table props causing issues in Storybook

Currently, I am utilizing MaterialUI with some modifications to create a personalized library. My tool of choice for documentation is Storybook, using Typescript. An issue I have encountered is that the storybook table props are not consistently auto-gene ...

The NgModel within the parent component is expected to mirror the state of the child component

My Angular 10 project includes a library with a wrapper component around a primeng-component. The primeng-component utilizes ngModel. I am trying to set the ngModel in the parent-component accessing the wrapper-component, and I want any changes made to the ...

Error: Unable to locate metadata for the entity "BusinessApplication"

I have been utilizing TypeORM smoothly for some time, but out of the blue, I encountered this error during an API call: EntityMetadataNotFound: No metadata for "BusinessApplication" was found. at new EntityMetadataNotFoundError (C:\Users\Rob ...

No data is generated when choosing from the dropdown menu in mat-select

I have a select function where all options are selected, but the selected sections are not shown. When I remove the all select function, everything works fine. Can you help me find the error? Check out my work on Stackblitz Here is my code: Select <m ...

Packaging a NodeJS project in Visual Studio - A step-by-step guide to creating and setting up an N

In my VS2013 solution, I have a combination of NodeJS (using TypeScript) and C# class library projects connected by EdgeJS. Among the NodeJS projects, one serves as a library for a RabbitMQ bus implementation, while two are applications meant to be hosted ...

Vite HMR causes Vue component to exceed the maximum number of recursive updates

After making changes to a nested component in Vue and saving it, I noticed that the Vite HMR kept reloading the component, resulting in a warning from Vue: Maximum recursive updates exceeded... Check out the online demo on stackblitz. Make a change in Chi ...

Navigating through pages: How can I retrieve the current page value for implementing next and previous functions in Angular 7?

Greetings, I am a new learner of Angular and currently working on custom pagination. However, I am facing difficulty in finding the current page for implementing the next and previous functions. Can anyone guide me on how to obtain the current page value? ...

A guide to implementing vue-i18n in Vue class components

Take a look at this code snippet: import Vue from 'vue' import Component from 'vue-class-component' @Component export default class SomeComponent extends Vue { public someText = this.$t('some.key') } An error is being thr ...

Developing typeScript code that can be easily translated and optimized for various web browsers

Can TypeScript alleviate the worry of having to use code such as this (especially when considering browsers like IE that may not support indexOf)? arrValues.indexOf('Sam') > -1 Does the transpiling process in TypeScript generate JavaScript c ...

Creating cookie files in the web browser following the activation of a stripe webhook handler

Although I don't have a strong background in backend development, I am wondering if it is possible to set browser cookies for customers after they complete a payment using Stripe's checkout session completed event. I am currently working with the ...

Encountering a 503 ERROR message stating "The request could not be satisfied" following the implementation of getServerSideProps in the pages directory

For my project, I am using the Next.js app hosted on AWS Amplify. Everything was running smoothly until I implemented getServerSideProps to fetch data from a Lambda function for SEO purposes. The code for getServerSideProps can be found in the pages folde ...

Introduction to React with Typescript: Greeting the World

I am attempting to create a Hello World React application with Typescript. Below is the code I have written. Method 1 works without any issues, but method 2 throws an error. Method 1 - TypeScriptComponent.tsx import React from 'react' import Re ...

Steps to forward a restricted user to a specific webpage

I am currently utilizing NextJs and am in the process of creating a redirecting function for users who have been banned or blocked from accessing the DB/session. My attempt at this involved: redirect.js, where I created a custom redirect function. impo ...

Utilizing TypeScript generic types as a key for an object

function createRecord<T extends string>(key: T): Record<T, string> { return { [key]: 'asdf' }; } Encountering an issue: The type '{ [x: string]: string; }' is not matching with the expected 'Record<T, st ...