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):
<img :src="banner" alt="Daytime Banner">
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.
The error is that in your useTheme.js file you are declaring the 'theme' state inside the function, so you are creating a local state each time you call the useTheme() function instead of a global one.
Change your code to this:
import { ref, watchEffect } from 'vue';
const theme = ref(JSON.parse(localStorage.getItem('theme') || 'false'));
watchEffect(() => {
localStorage.setItem('theme', String(theme.value));
});
export default function() {
return { theme };
}