Troubles with Vue and localStorage for storing a theme's data

I've been struggling with this issue for a while now while working on a Vue site. I have not been able to find a solution for my specific bug in other discussions.

The concept should be straightforward - I want to have a switch that toggles a value between 'light' and 'dark', and then bind the class to that value.

<template>
  <div id="app" :class='themeValue'>
    <!-- Switch component from Buefy UI !-->
    <b-switch size='is-large' type='is-dark' v-model='theme'></b-switch>
    <!-- Other components !-->
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      theme: localStorage.getItem('theme') || false
    }
  },
  watch: {
    theme: function() {
      localStorage.setItem('theme', this.theme)
    }
  },
  computed: {
    themeValue: function() {
      return this.theme ? 'light' : 'dark'
    }
  }
}
</script>

<style lang="scss">
@import './_variables.scss';

.dark {
  color: $light;
  background-color: $background;
}

.light {
  color: $dark;
  background-color: $lightbackground;
}
</style>

I have experimented with many variations of the code, such as using `mounted()` to set `this.theme`, using an external component with `$emit`, and more.

The expected result is to default to the dark theme unless a value for 'theme' is stored in localStorage, in which case it should default to that value. The switch component should always reflect the state of the theme (i.e. if saved to light theme, the switch should default to `true`).

However, the current behavior of the code is to always default to the light theme, and the switch defaults to `false`. This leads to inconsistency where the light theme is applied when `theme === true`. The first switch press does not change the theme but does change itself to `true`, and subsequent presses work correctly (`true` applies `.light` class, `false` applies `.dark` class).

EDIT: I realized that localStorage was storing the true/false values as strings. Although, a refined implementation using JSON.parse could have worked, I opted for a `mounted` method with `if (localStorage.getItem('theme') === 'true')` which resolved the issue. It's frustrating that it took me 4 hours to figure this out.

Answer №1

After some troubleshooting, I managed to get it to work on my local setup by rearranging the 'or' statement and updating the property name to 'themes'.

<template>
  <div id="app" :class='themeValue'>
    <!-- Switch component from Buefy UI !-->
    <button size='is-large' type='is-dark' @click='themes = !themes'>klik</button>
    <!-- Other components !-->
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      themes: false || localStorage.getItem('theme')
    }
  },
  watch: {
    theme: function() {
      localStorage.setItem('theme', this.theme)
    }
  },
  computed: {
    themeValue: function() {
      return this.themes ? 'light' : 'dark'
    }
  }
}
</script>

<style lang="scss">


.dark {
  color: white;
  background-color: black;
}

.light {
  color: black;
  background-color: white;
}
</style>

My recommendation for you is to rename your watch function to something like updateTheme, and swap the conditional statement within your data property - this tweak should resolve the issue :)

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

What is the best method for placing an element above all other elements on a page, regardless of the layout or styles being used?

I want to create a sticky button that remains fixed on the page regardless of its content and styles. The button should always be displayed on top of other elements, without relying on specific z-index values or pre-existing structures. This solution must ...

The JSON.parse function encounters issues when trying to parse due to a SyntaxError: Unexpected character found after JSON at position 2, causing it to be unable

I've encountered an issue with my JavaScript code when trying to retrieve the value of the details field from JSON data. While all other values are successfully passed to their respective fields, the details field generates the following error: "Unabl ...

Issues with lazy loading in swiper.js when trying to display multiple images per slide

I recently tried using swiper.js and had success with the lazy loading demo. However, I encountered an issue where only one image per slide was showing up, despite wanting to display 4 images per slide. <div class="swiper-container"> <div cla ...

Troubles with Angular elements not aligning correctly when using the "display: block" property

When using an angular element for a directive with "display: block", it may not automatically take up 100% of the width of the parent container. In order to ensure that it does, the width must be explicitly set to "100%" in the CSS. Despite setting "width: ...

Retrieve JSON data generated within a JavaScript-powered webpage

My issue involves two HTML pages: 1) The first HTML Page (page1.html): <html lang="en"> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js" type="text/javascript"></script> <script type="text/ ...

What is the best way to transfer form data to another function without causing a page refresh?

Currently, I am in the process of developing a series of web applications using REACT JS. One specific app I am working on involves a modal that appears upon a state change and contains a form where users can input their name along with some related data. ...

Is it possible for the Redux state to become unsynchronized?

const SortingFunction = ({ dataState, updateState }) => { const handleClick = () => { const newState = JSON.parse(JSON.stringify(dataState)) // Make necessary updates to the new state based on the current dataState updateState(newStat ...

What is the iPad version of the onmousemove event?

I am currently facing an issue with a website on my iPad. Everything seems to be in order except for the onmousemove method. I am looking for a way to have onmousemove activated when the user swipes their finger across the screen. ...

"AngularJS fails to pass the value of a checkbox within ng-repeat and

I have already asked this question, but the previous solutions did not resolve my issue. I am attempting to pass the value of a checkbox to a controller in AngularJS, but I keep getting an 'undefined' message. I am new to AngularJS. Here is the ...

Exploring the intricacies of managing nested data in a Firebase Database (web)

I understand this question may have similarities to others already asked, so my apologies in advance. I am seeking a clear, up-to-date solution that aligns with my expectations. https://i.sstatic.net/dQ9ih.jpg If I have an object labeled "Item One", how ...

Considering a Servlet for managing AJAX requests?

Looking for advice on best practices for implementing a yes or no question with AJAX requests. Open to feedback if I make any missteps along the way. I have a specific Servlet (AjaxServlet?) designated to handle all AJAX requests AjaxServlet is mapped t ...

Verify if there are DOM elements located within a DIV container, execute the functions associated with those elements sequentially

I am in the process of creating a game using HTML, CSS, and JavaScript. My focus right now is on manipulating DOM elements without relying on the canvas tag. The goal is to develop a pseudo graphical programming language, similar to the environment provide ...

Setting the $dirty flag to true when a value is entered in the text box, but not the other way around

When I enter a value in the text box, myForm.$dirty gets set to true. However, the flag does not revert back to false when I delete all values from the text box. Why is this happening and how can I fix it? <input name="input" ng-model="myModel.text"& ...

A quick guide on automatically populating text boxes with characteristics of the item chosen from a drop-down menu

On my webpage, I am looking to automatically populate textboxes with information (such as common name, location, etc.) of the selected shop from a dropdown list without having to refresh the page. Here is the dropdown list: <select id="shops" class="f ...

I keep encountering an error that says "ReferenceError: localStorage is not defined" even though I have already included the "use

I have a unique app/components/organisms/Cookies.tsx modal window component that I integrate into my app/page.tsx. Despite including the 'use client' directive at the beginning of the component, I consistently encounter this error: ReferenceErr ...

Selenium on Sauce Labs does not successfully load the page in Firefox after clicking

An issue has arisen where a test that functions properly with selenium webdriver locally is timing out when executed remotely on saucelabs.com. Notably, the test runs smoothly for Chrome in both local and remote scenarios. The problem seems to lie in the ...

Unable to recognize click event within the ng-click function

I need to identify when a click event occurs on an SVG element, specifically on a g element within the SVG element. Currently, I have created this JSFiddle The ng-click function is working properly, but unfortunately, the click event is not being detecte ...

How can I access the id_lang variable in React JS from outside its scope?

How do I access the 'id_lang' variable outside of the render function in order to pass it down for checking? const Navbar = () => { const getID = async (id) => { let id_lang = id; console.log(id_lang); } ret ...

What is the reason for not storing information from MySQL?

Looking to extract data from a website using this JavaScript code. var i = 0 var oldValue = -1 var interval = setInterval(get, 3000); function get(){ var x= $($('.table-body')[1]).find('.h-col-1') if(i!=5){ if(oldValue != x){ old ...

Error: Laravel API request unsuccessful

After seeking advice in larachat and conducting thorough research on Google, I discovered that while similar inquiries have been made in the past, none of the suggested solutions seem to work for my particular case. My current challenge involves loading c ...