Issue with Local Storage: Value not being saved, instead [object MouseEvent] being stored

I am truly grateful for the help from @zim as it allowed me to drastically simplify my code for 2 buttons that store true/false values locally. However, I am facing an issue where the button click is registering as [object MouseEvent] instead of True/False. Despite my best efforts, I have reviewed this thoroughly but am unable to determine why the correct value is not being stored.

Markup

<div>
    <button type="button" @click="clickPrivateChat">
        <a key="privateChat" href="#" :class="privateChat?'bg-green-900 hover:bg-green-700':''" class="bg-red-900 text-gray-100 hover:bg-red-700 hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium">
            <ChatIcon class="h-6 w-6 text-white"/>
            <span class="pt-2">Private Chat {{ privateChatOnOrOff }}</span>
        </a>
    </button>
</div>

<div>
    <button type="button" @click="clickAllSounds">
        <a key="privateChat" href="#" :class="allSounds?'bg-green-900 hover:bg-green-700':''" class="bg-red-900 text-gray-100 hover:bg-red-700 hover:text-white group w-full p-3 rounded-md flex flex-col items-center text-xs font-medium">
            <VolumeUpIcon class="h-6 w-6 text-white"/>
            <span class="pt-2">All Sounds {{ allSoundsOnOrOff }}</span>
        </a>
    </button>
</div>

Script:

data() {
    return {
        privateChat: (localStorage.getItem("privateChat") === true) ? true : false,
        allSounds: (localStorage.getItem("allSounds") === true) ? true : false
    }
},
computed: {
    privateChatOnOrOff() {
        return this.privateChat ? 'ON' : 'OFF'
    },
    allSoundsOnOrOff() {
        return this.allSounds ? 'ON' : 'OFF'
    }
},
methods: {
    clickPrivateChat(value) {
        this.privateChat = !this.privateChat
        localStorage.setItem("privateChat", value)
    },
    clickAllSounds(value) {
        this.allSounds = !this.allSounds
        localStorage.setItem("allSounds", value)
    }
}
setup() {
    const mobileMenuOpen = ref(false)
    const privateChatEnabled = ref(privateChat)
    let privateChatValue = localStorage.getItem("privateChat")
    let privateChat = (privateChatValue === 'true')
    const allSoundsEnabled = ref(allSounds)
    let allSoundsValue = localStorage.getItem("allSounds")
    let allSounds = (allSoundsValue === 'true')

    return {
        sidebarNavigation,
        userNavigation,
        mobileMenuOpen,
        tabs,
        userlists,
        team,
        activityItems,
        privateChatEnabled,
        allSoundsEnabled,
    }
}
},

Answer №1

Clarification on @Barmar's answer:

The reason why you're seeing [object MouseEvent] in Local Storage is because your click-handlers are storing the event data (the value being the MouseEvent object from the click event) instead of the Boolean value changed inside the handler. Since Local Storage can only store strings, it converts the MouseEvent object into a string, resulting in [object MouseEvent], as demonstrated below:

console.log(new MouseEvent({}).toString())

The solution is straightforward - store the intended Boolean value:

export default {
  methods: {
    clickPrivateChat (value) {
      this.privateChat = !this.privateChat 
      // localStorage.setItem("privateChat", value) ❌ value is a MouseEvent object

      localStorage.setItem("privateChat", this.privateChat) // ✅
    },
    clickAllSounds (value) {
      this.allSounds = !this.allSounds
      // localStorage.setItem("allSounds", value) ❌ value is a MouseEvent object

      localStorage.setItem("allSounds", this.allSounds) // ✅
    }
  }
}

When retrieving data from Local Storage, make sure to convert the stored string back into a Boolean:

export default {
  data() {
    return {
      privateChat: localStorage.getItem("privateChat") === "true",
      allSounds: localStorage.getItem("allSounds") === "true",
    }
  }
}

I see that you have been doing this in the setup() function but assigning the result to temporary variables. To correctly declare props in setup(), replace the data() props with refs:

import { ref }  from 'vue'

export default {
  // BEFORE:
  // data() {
  //  return {
  //    privateChat: localStorage.getItem("privateChat") === "true",
  //    allSounds: (localStorage.getItem("allSounds") === "true",
  //  }
  //},

  // AFTER:
  setup() {
    const privateChat = ref(localStorage.getItem("privateChat") === "true")
    const allSounds = ref(localStorage.getItem("allSounds") === "true")

    return {
      privateChat,
      allSounds,
    }
  }
}

demo 1: Options API with Composition API

demo 2: Composition API only

Answer №2

value represents an Event object, which cannot be directly stored in localStorage since it only supports string values.

To store the value of this.privateChat and this.allSounds, you should convert them to JSON before saving and parse them when accessing.

data() {
    return {
      privateChat: (JSON.parse(localStorage.getItem("privateChat") || "false") === true) ? true : false,
      allSounds: (JSON.parse(localStorage.getItem("allSounds"), "false") === true) ? true : false,
    }
  },
  computed: {
    privateChatOnOrOff() {
      return this.privateChat ? 'ON' : 'OFF'
    },
    allSoundsOnOrOff() {
      return this.allSounds ? 'ON' : 'OFF'
    }
  },
  methods: {
    clickPrivateChat(value) {
      this.privateChat = !this.privateChat
      localStorage.setItem("privateChat", JSON.stringify(this.privateChat))
    },
    clickAllSounds(value) {
      this.allSounds = !this.allSounds
      localStorage.setItem("allSounds", JSON.stringify(this.allSounds))
    }
    setup() {
      const mobileMenuOpen = ref(false)
      const privateChatEnabled = ref(privateChat)
      let privateChatValue = localStorage.getItem("privateChat");
      let privateChat = (privateChatValue === 'true')
      const allSoundsEnabled = ref(allSounds)
      let allSoundsValue = localStorage.getItem("allSounds")
      let allSounds = (allSoundsValue === 'true')

      return {
        sidebarNavigation,
        userNavigation,
        mobileMenuOpen,
        tabs,
        userlists,
        team,
        activityItems,
        privateChatEnabled,
        allSoundsEnabled,
      }
    },
  },

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

text box with an immobile header

As the browser window size decreases, the layout changes. However, when scrolling down, the search text box moves up and is no longer visible due to its lack of fixation. How can I make the search text box stay fixed as I scroll down? I tried implementing ...

Avoiding repetition in json array using reactjs with the help of axios

After receiving guidance from @Akrion, I managed to resolve the issue! Check out my comments below our conversation for the solution. I am relatively new to reactJS and axios, but I recently collaborated with a classmate on a project. Now, I find myself s ...

Is it possible to retrieve data from a database using jQuery and store it in separate variables?

I am able to print out one field from a table, but I want to display all fields in separate tables. How can I achieve this? Below is my save/load code: // Save/Load data. $('').ready(function() { if($.cookie('code')) { $.aj ...

mysql nodejs function is returning a null value

Kindly review the contents of the dbfn.js file /*This is the database function file*/ var db = require('./connection'); function checkConnection(){ if(db){ console.log('We are connected to the Database server'.bgGreen); ...

I'm attempting to utilize a basic webcam capture upload feature, but it seems that the upload function is not functioning properly

UPDATE: This is the complete code that I simply copied and pasted. <!DOCTYPE HTML> <head> <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> <script language="JavaScript" type="text/javascrip ...

Is dynamic data supported by Next.js SSG?

I'm currently developing a web application with Next.js and I need clarification on how Static generated sites work. My project is a blog that necessitates a unique path for each blog entry in the database. If I were to statically generate my web appl ...

Streamline a javascript code with numerous elements

Seeking assistance in simplifying this code Currently, I find myself constantly updating this code each time a new entry is uploaded. I am looking for a solution where there is a single script that can identify the element IDs ("#rolly" or "#lagrimas") a ...

Using a series of identical divs to dynamically update the image URL

Greetings! I am a newcomer to the world of web development and I have decided to hone my skills by creating a small website for my mother! My goal is to replicate a specific div multiple times while changing only the image URL and the heading caption. < ...

Seeking guidance on designating an additional disk for fs.readdir(path) within an Electron-vue application?

Issue: I am facing a problem with the breadcrumbs component in my project, which is utilizing file explorer functionality from this specific project. The issue at hand is related to changing the disk being displayed by the component. Upon clicking on any ...

Navigating through sections in NextJS-14: Utilizing useRef for seamless scrolling

In the past, I had developed an older portfolio website using Vite React + TS and implemented useRef for scrolling to sections from the Navbar. Now, my goal is to transition this portfolio to NextJS 14. I transferred my old components and style folders in ...

When an element is appended, its image height may sometimes be mistakenly reported as

I am dynamically adding divs and I need to retrieve the height and width of an image. Based on this information, I have to apply CSS to the MB-Container class. For example: if the image is portrait orientation, set container width to 100%. If it's ...

Transforming the typical click search into an instantaneous search experience with the power of Partial

I am working on a form that, when the user clicks a button, will display search results based on the entered searchString. @using (Html.BeginForm("Index", "Search")) { <div id="search" class="input-group"> @Html.TextBox("searchString", n ...

Hide elements forever once the form is submitted

I'm seeking help to figure out how to make certain elements disappear after a form submission on my website's dashboard page. Specifically, I need to hide three elements once the user has submitted a form. Elements that need to be hidden: .vc_t ...

Avoid unnecessary re-renders in ReactJS Material UI tabs when pressing the "Enter

I've created a user interface with tabs using material-ui in reactJS. The issue I'm facing is that every time a tab is selected, the content under that tab reloads, causing performance problems because there's an iFrame displayed in one of t ...

Adding turbolinks to an HTML document can be achieved without the need for a

Recently delving into the world of turbolinks, I discovered that it can be employed independently without relying on a client-side javascript framework. Eager to test this out, I created a bootstrap 4 template and attempted to install it. Firstly, I downl ...

retrieve the coordinates of the northwest and southeast corners of a group of markers displayed on a Google Map

Is there a more efficient way to get the NE and SW corners of a set of markers on a Google map without iterating over each marker individually using JavaScript or Google functions? function fnSetBounds(){ var lowLat = 90; var highLat ...

Import existing data from a pre-filled form - VueJS - Bootstrap-Vue

I'm facing an issue with a form that has linked selects. When one select is filled, the other select should also be filled with the corresponding code. However, when opening the modal with the field value, it fails to load the value. I suspect this mi ...

When the down key is pressed in a textarea, choose the list item

I have HTML similar to the following <div class="row"> <textarea id="txtArea" ng-model="input" ng-change="handleOnChange(input);getSearchField(input);" ng-click="search(input)" ng-focus="search(input);" ...

Contrasting the uses of element(...) versus element(...).getWebElement() in Protractor

What is the advantage of using element(...).getWebElement() instead of element(...) when they both perform similarly? Why are there two different APIs for the same purpose? ...

Utilize the material-ui dialog component to accentuate the background element

In my current project, I am implementing a dialog component using V4 of material-ui. However, I am facing an issue where I want to prevent a specific element from darkening in the background. While I still want the rest of the elements to darken when the ...