skip to Main Content

I’m trying to change a picture (daytime picture vs nighttime picture) dynamically when a person hits the light button. It works, but I have to refresh the page for the picture to show. Daytime and nighttime are basically just booleans of ‘true’ or ‘false’ for my theme variable.

I tried coding it this way:

useTheme.js:

import { ref, watchEffect } from 'vue';

export default function useTheme() {
    const theme = ref(JSON.parse(localStorage.getItem('theme') || 'false'));

    watchEffect(() => {
        localStorage.setItem('theme', String(theme.value));
    });

    return { theme };
}

App.vue:

const { theme } = useTheme(); // Access the shared state.

const toggleTheme = () => {
  theme.value = !theme.value;
  document.body.classList.toggle('dark-theme', theme.value);
  localStorage.setItem('theme', JSON.stringify(theme.value));
}

Home.vue (Where the problem resides):

  • Part of the HTML:
<img :src="banner" alt="Daytime Banner">
  • Calculating the daytime vs nighttime:
import DayTimeBanner from "@/assets/banner-city-daytime.png";
import NightTimeBanner from "@/assets/banner-city-nighttime.png";
...
const { theme } = useTheme(); // Access the same shared state.

const banner = computed(() => theme.value ? NightTimeBanner : DayTimeBanner);

Any clue on what might be going on? Changes to the theme background is reactive, but for the banner, I have to refresh the page for the image to pop up.

2

Answers


  1. One of the reasons might be that useTheme does not return a reactive value. Try using ref or reactive

    Login or Signup to reply.
  2. Would be the easiest if you could apply a CSS instead of an asset to src.

    Predefine the two classes for both of the banners ex:,

     background: lightblue url("/assets/banner-city-daytime.png") no-repeat fixed center;
    

    I assume you know your way around CSS 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search