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

Retrieve all values of a specific enum type in TypeScript

When working with Typescript, I am looking to retrieve all values of an enum type and store them in an array. In C#, a similar method would look like this: public static TEnum[] GetValues<TEnum>() where TEnum : Enum { return Enum.GetValues(typeof ...

Conceal the secret key for the Firebase FCM service worker

I am facing an issue with Firebase FCM tokens where I need to hide key values from the service worker. Despite trying environment variables, they are not being applied. Can anyone provide a solution for this? I am looking to receive payload through the on ...

Next.js is optimized for simplicity and ease-of-use, making it

I'm currently experimenting with integrating the Express Router in Next.js by utilizing their example of a custom-express-server as my starting point. My approach involves external route definitions in routes/router.js, which looks like this: Here is ...

What is the best way to retrieve information from multiple pages of my REST API?

Recently, I integrated a search engine into my application and now I need to gather all the data available for a particular resource, such as all the posts made by a user. The response I receive from my API looks something like this: { "count": 2, ...

typescript defining callback parameter type based on callback arguments

function funcOneCustom<T extends boolean = false>(isTrue: T) { type RETURN = T extends true ? string : number; return (isTrue ? "Nice" : 20) as RETURN; } function funcCbCustom<T>(cb: (isTrue: boolean) => T) { const getFirst = () => ...

Combining SSR and client data within components is a unique feature of Nextjs

I recently encountered an issue where the same component displayed mixed data due to randomization. The HTML ended up with jumbled data, partly from server-side rendering (SSR) and partly from client-side rendering. See the code snippet below: const Comp ...

Encountering crashes while initializing the router in the constructor of a service in Angular 4.3

I've been scratching my head over this problem. It seems like I'm overlooking something simple. Let me show you what's inside my home.component.ts file: import { Component, OnInit } from '@angular/core'; import { AuthService } f ...

Using TypeScript or JavaScript, set object keys as fields of a class

I am looking for a way to update the properties of this class dynamically using an object export default class Foo { private accessKey: string; private workspaceId: string; private api: AxiosInstance; public bar: string; public name: s ...

Insert a new item into the array located within an Observable entity

In my angular application, I have a page where I am showcasing an object that contains an array of comments within it. This object is loaded into my class as an Observable and then displayed in the HTML using: <div class="container-fluid mt--7" ...

Utilizing nested namespaces for optimal organization and clarity

Is it possible to export a namespace A with another namespace B nested within it? For example: // b.ts export namespace B { export const val = 'val'; } // a.ts export namespace A { //... some thing import B as namespace } --- the above wil ...

ts-node: The colon symbol was not expected in this context

As I work on developing a backend server for my application, I made the decision to switch from using babel-node as the executor to utilizing ts-node. The command defined in my package.json file is: "server": "cd server && ts-node --project tsconf ...

Aligning two identical components within the same container when triggered by a single click

Currently, I am exploring Angular 2 and Typescript and have been developing a pager component for a table. The pager functions correctly, but I have encountered an issue with having two pagers - one above the table and one below it. When the next button on ...

Troubleshooting the ReferenceError: Blob is not defined problem with the heic2any library in a Next.js application

Currently, I am encountering an issue where everything is properly implemented and functioning smoothly. However, the main problem arises when I attempt to reload the page, as it results in an error message: ReferenceError: Blob is not defined. This issue ...

Enhancing AWS Amplify Auth elements using TypeScript

My goal is to enhance the existing Auth components within AWS Amplify like SignIn, SignUp, etc. by customizing the showComponent() function to display a personalized form. I found a helpful guide on how to achieve this at: While working on my nextjs proje ...

Encountering a 404 error when using the NestJS GET function within the service and controller

I am facing an issue with creating simple GET logic. When I test it in Postman, I keep receiving a 404 error. books.service.ts contains the following basic logic: constructor( @InjectRepository(Books) private readonly booksRepo: Repository<Boo ...

Identifying misspelled names in shared resources textures during PIXI.js loading

Our game utilizes TypeScript, Pixi.js, VSCode, and ESLint. We maintain a dictionary of image files as follows: export function getAllImages(): {name: string, extension: string}[] { return [ {name: 'tile_lumber', extension: '.svg ...

Implementing image uploads in a React application on a Digital Ocean hosted server

I am currently working on a project that involves uploading images from a react application. const accessToken = getCookies(null, 'token'); const formData = new FormData(); formData.append('image', imageFile); ...

Tips for ensuring session token verification remains intact upon reloading

I am currently in the process of developing a website using the Next.js framework and I am seeking advice on how to prevent the reload effect that occurs when transitioning from the login page back to the main page for just a fraction of a second. Below i ...

International replacement of external interface exportation

Currently, I am utilizing the @react-native-firebase/messaging library and invoking the method messaging().onNotificationOpenedApp(remoteMessage => ....) I am aiming to replace the property data within the type of remoteMessage in order to benefit from ...

Issues with identifying the signature of a class decorator arise when invoked as an expression

I've been following this coding example but I'm running into issues when trying to compile it. Any suggestions on how to troubleshoot this error? import { Component } from '@angular/core'; function log(className) { console.log(class ...