The functionality of localStorage seems to be dysfunctional in Nuxt js when running in SSR mode

I am encountering an issue while trying to add items to a cart using vuex. The console is showing an error and the products on the page are not displaying correctly. Can someone please guide me on how to resolve this problem? The error in the console is:

client.js?06a0:103 SyntaxError: Unexpected token u in JSON at position 0
    at JSON.parse (<anonymous>)
    at Store.initializeStore (index.js?9101:14)
    at wrappedMutationHandler (vuex.esm.js?2f62:844)
    at commitIterator (vuex.esm.js?2f62:466)
    at Array.forEach (<anonymous>)
    at eval (vuex.esm.js?2f62:465)
    at Store._withCommit (vuex.esm.js?2f62:624)
    at Store.commit (vuex.esm.js?2f62:464)
    at Store.boundCommit [as commit] (vuex.esm.js?2f62:409)
    at VueComponent.mounted (default.vue?ec86:82)

Below is the store.js code where I am utilizing localStorage:

export const state = () => ({
    cart:{
        items:[],
    },
    isAuthenticated: false,
    token: '',
    isLoading: false,

})
  
export const mutations = {
    initializeStore(state) {
        if (localStorage.getItem('cart')) {
          state.cart = JSON.parse(localStorage.getItem('cart'))
        } else {
          localStorage.setItem('cart', JSON.stringify(state.cart))
        }
    },
    addToCart(state, item) {
        const exists = state.cart.items.filter(i => i.product.id === item.product.id)
        if (exists.length) {
          exists[0].quantity = parseInt(exists[0].quantity) + parseInt(item.quantity)
        } else {
          state.cart.items.push(item)
        }
        localStorage.setItem('cart', JSON.stringify(state.cart))
    },

}

export const actions = {

}

This is default.vue file where I am attempting to access localStorage from vuex:

export default {
  data(){
    return{
      title:'QL Gadgets',
      cart:{
        items:[]
      },
    }
  },
  mounted(){
    this.$store.commit('initializeStore')
  },
  computed:{
    cartTotalLenght(){
      let totalLenght = 0
      for(let i=0; i < this.cart.items.length; i++){
        totalLenght += this.cart.items[i].quantity
      }
      return totalLenght
    }
  },
  methods:{
    handleClick(){
        if(this.$refs.menu.classList.contains('hidden')){
            this.$refs.menu.classList.remove('hidden')
        }
        else{
            this.$refs.menu.classList.add('hidden')
        }
    }
  },
}

Answer №1

It seems the issue lies in storing a non-JSON-parseable string or having an empty response in the local storage (undefined begins with u). Make sure to check your browser's local storage using tools like Chrome or Firefox to verify this.

In any case, it is important to handle errors when accessing local storage or parsing data. For instance, upon the first visit of a user, there might be no data stored and attempting to parse it with JSON.parse can result in failure. Consider implementing error handling logic like the following:

export const mutations = {
  initializeStore(state) {
    try {
      state.cart = JSON.parse(localStorage.getItem('cart'))
    } catch {
      localStorage.setItem('cart', JSON.stringify(state.cart))
    }
  }
}

Answer №2

The ability for the server to access browser local storage is limited because local storage is a client-side feature. It appears that localStorage.getItem('cart') is returning undefined, leading to an error when trying to parse undefined as JSON.

During server render, your store is triggering the appropriate function due to the mounted hook in your template.

To resolve this issue, you should retrieve localStorage.getItem on the client side and then either transfer it back to the server (using server middleware for further processing if node access is required) or process it on the client side and update the store accordingly.

In addition, utilizing vuex-persistedstate can enhance this functionality. Alternatively, you can choose to persist your cart selectively after the initial commit, allowing the server to access it during subsequent app launches.

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

Extracting the name of the file from the image's web address

I have created a simple Chrome extension for personal use and sharing with friends. I am dealing with URLs that have various formats, such as: i.imgur.com/abcd123.png or imgur.com/a2b3c78 or even i.imgur.com/herp321.png?1 All I need from these URLs are t ...

PHP sending only a single space in an email

My HTML form works perfectly fine, except for one field! The issue arises with a particular text field that I fill out using a button and a short JavaScript function. Could this be causing a conflict with the PHP code? The problematic text field is: inpu ...

Exploring Vue 3: Choosing between using import statements in main.js and configuring additionalData in vue.config.js to load a global scss file

I am attempting to load a global SCSS file using the "vue.config.js" file. vue.config.js module.exports = { css: { loaderOptions: { sass: { additionalData: `@import "@/assets/common.scss";` } } } } If I include the style tag in my App. ...

Can you explain the concept of a TransientTransactionError within Mongoose (or MongoDB)?

Two important files in my project are server.js and db.js. The db.js file is responsible for interacting with the database using Mongoose, while server.js calls functions from db.js: var mongoose = require('mongoose'); mongoose.connect('&ap ...

Leveraging Components within Components in Vue 2

Here is the code snippet I am working with: import './menu-item'; import ItemImage from "./item-image"; Vue.component('quest-card', { props: { title: String, isFree: Boolean, points: Number, ...

Tips for creating a hierarchical multilevel datatable with JavaScript

I am currently working on implementing a multi-level datatable without relying on any external plugins or libraries. My goal is to achieve this using pure JavaScript, JQuery, or AngularJS. I have explored the following resources: Traverse all the Nodes of ...

Modify the current link's <li> class

I am facing an issue with the code below which is supposed to change the class of li based on whether the browser URL matches the href attribute within that li. The current problem I am encountering is that the code changes the class for all li elements, ...

Is there a way to switch the sorting order on a Bootstrap page using a button without having to refresh the page?

I'm currently working on a template for an app that already exists and would like to add a button to change the sort order of displayed elements on a webpage. The page is styled using Bootstrap 5.3, so I have access to jQuery and other Bootstrap featu ...

How can I add an image to a canvas using a button?

Having trouble with my studies and looking to create a custom shirt website. Posted below is the beginner code I have: If anyone knows how to upload an image onto a shirt canvas using a button, as well as change the shirt color with another button, please ...

the 'class' keyword cannot be utilized in ECMA6

I attempted to execute a class in ECMA2015 but encountered the following error: class Task { constructor(name) { this.name=name; this.completed = false; }; } I received the error below: class Task { ^^^^^ SyntaxError: Unexpected reserved word} Not ...

Other options besides re-flowing and repainting

After doing some research on various platforms like Stack Overflow, I've come across information stating that re-paints and re-flows can be quite taxing on a browser's resources. I am interested in learning about alternative CSS/JS techniques to ...

When working with nested contexts in React, is there a way to avoid causing a rerender of the child context when changes are made to the parent context?

I'm currently utilizing multiple contexts to extract data from different locations within my database. In the code snippet below, the 'path' value that is passed to the provider indicates the specific path within the database. A record in & ...

"Concealing Querystrings in Node.js and AJAX: A Step-by-Step

I want to create a simple login form using the ajax Post method. However, I am having issues with the querystring still appearing in the URL. Can anyone help me resolve this issue? Thank you for any assistance! [ https://i.stack.imgur.com/R76O4.png http ...

Tips for rearranging objects within a jsPDF document to prevent vertical overlap when a table grows in size

I am new to React and Javascript. I have been struggling to find a solution to my issue while trying to create a .pdf document for a customer invoice using "jsPdf" along with its plugin "jspdf-autoTable". So far, everything is being generated correctly by ...

Develop a React component that organizes an array based on specified index ranges in JavaScript

Imagine having an array structured like this: let numbers = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, 18, 19]; I am interested in creating a React component that displays the elements of the array in groups of 10. The desired output should look like t ...

Guide for Extracting a String in JavaScript that Includes Numerals for Color Code Alteration, Resulting in Formats like 32m+ or 31m-

Attempting to create a Firebase cloud function in JavaScript that sends email notifications for any changes in the Firebase remote config. Upon each remote config change, the string received is in the following format: { parameters: { [32m+ newer_value: ...

JavaScript slowness

Currently, I am developing a test page that consists of buttons triggering various scripts. One of the functionalities I am trying to implement is changing the background color every second for 5 seconds, cycling through a total of 5 different colors. Desp ...

How to show line breaks in MySQL text type when rendering in EJS

In my MySQL table, I have a column called PROJ_ABOUT with the type TEXT. I have inserted several rows into this column and now I am trying to display this information in my Express.js app using the ejs engine. <h2>About project</h2> <p> ...

Attempting to extract JavaScript URLs using scraping methods, however, receiving an empty string when utilizing

I need help accessing and extracting data from a URL that is embedded within a specific tag. The tag in question looks like this: <script src="http://includes.mpt-static.com/data/7CE5047496" type="text/javascript" charset="utf-8"></script> S ...

Configuring multiple data sources in VueJS allows you to seamlessly connect

I have a Vue app with two data tables. Cash: [code, description, cash] Upload: [bank, id] In my update function, I need to retrieve [bank, id] from the Upload table and [cash] from the Cash table. Unfortunately, I am unsure how to do this. Can someone p ...