Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useStorage reactivity between components not working #1595

Closed
7 tasks done
JEK58 opened this issue May 12, 2022 · 9 comments · May be fixed by HadaIonut/DefiantMoon#25 or shanzufeng/vite-qiankun#5
Closed
7 tasks done

useStorage reactivity between components not working #1595

JEK58 opened this issue May 12, 2022 · 9 comments · May be fixed by HadaIonut/DefiantMoon#25 or shanzufeng/vite-qiankun#5
Labels
bug Something isn't working

Comments

@JEK58
Copy link

JEK58 commented May 12, 2022

Describe the bug

If two components share the same local storage they do not respond reactive if one of them changes the value of the binding.
After a page reload they are in sync. But if the value is changed again they are not reactive as before.

Reproduction

https://play.vueuse.org/#N4IgDghgxg1hDmBTAziAXAbVAOwgW0XRADcBXRAWgBNE8BLEAGhGQHtSAnKQtEU7MDHhMQNZFA50wAFzqtsRAGrkABABFadFQAoAFhAA2AMxV1sKgGIdE2KLoCUp5CogqaxRAdZgz8FaVkDOmkATxcDLwB3ZxD2FWlWFUjJaUQVAFVsOg8OZEMVZTSAGToAIw4ISRQVI1YOAtUAJhUAMhUAZhFOAyJdaWkwZDQAemH+QXgAOihWPGGyShp6YaDS4bMaAA9JvAArVABfRhx8HhAAAQXSZERh5H1rKhE2Tm4icaERMQkpWXkiADKD0QVAaiHSN38gWCdBQky6HB6vD6AyGow+Uxmc0u5Gut3ulRB5wArJMAAyTACM62wW0mKDwk32ICOJwIRBxiDxwxm1me7C4ZwxXxQPxkcgUvAAwqwIogoH9zKwTCgbthZPlCioZXgwKxkDD5BlobIUAikSAUYMRmMBEJprNhpzubzECTyVSaXSGUzDgBdZhGOgGM1oUAAQTAYEmC3QoFSuoMEFSRAAPFRsgAdcwqeCSKgAXkzIAAfjUohQZgZcxAwBQACzF7MqFRgJPcIsgGbqmzSSu9xD1YK0ZD9nscJs53Sd8TWGyTlu1dWdvDyVgLlQAPmbKlTZjAAR3LZbUCTyGQndqHDwld08pgFH3h5AR+PoTAiE7dnvpVYmw3x4qBwsqfsWyCRMEdgAcedCFsWRghpsAIQdIdhSnesAaEYECkAY0jQS2xAUKuNAGJerDri+OYtsM245pGYBoCowDALUrAHAcO6pgAQpUKi0dmqbDBmxCbs8YrSEQdC6nU0jMf4NwAgkFRICoBw1MBeAqMWzo3DydSIMWADc2bSXqHBybx9RGJpKgAOSTMMVkxuQdnZu5tjyMgclsSoBYKYgSl1AgiDaPBFHFowNSGDc9hGfxwxAYg0icNgzgAEqIEYqa-iBEDYHRLLMM5sZhiACZtsmZzptkdEtlZTEsWxHGCcJtXiZIMhSTJFnyXiQUqWk6k2bM2kXFcemusZHndt5NQUX5AUDSFYUgGxkXRQYsXxaMSUpRwaUqJl2W5SG+WFRxBxAA

System Info

System:
    OS: macOS 12.3.1
    CPU: (8) arm64 Apple M1
    Memory: 143.25 MB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.13.0 - /usr/local/bin/node
    Yarn: 1.22.17 - ~/.yarn/bin/yarn
    npm: 8.1.0 - /usr/local/bin/npm
  Browsers:
    Brave Browser: 101.1.38.109
    Chrome: 101.0.4951.54
    Firefox: 98.0.2
    Safari: 15.4
  npmPackages:
    @vueuse/core: ^8.4.2 => 8.4.2 
    vue: ^3.2.33 => 3.2.33

Used Package Manager

yarn

Validations

@JMaylor
Copy link
Contributor

JMaylor commented May 17, 2022

I think this makes sense. You are essentially initialising two refs in two different components. They are both retrieving their initial value from storage, but they are then independent of each other.

If we unpack useStorage, what you essentially have here is:

const storageKey = 'key'
const initialValue = localStorage.getItem(storageKey)

const foo = ref(initialValue)
const bar = ref(initialValue)

watch(foo, foo => localStorage.setItem(storageKey, foo)
watch(bar, bar => localStorage.setItem(storageKey, bar)

When foo changes in the above, it will update the locally stored value.
However, bar does not have any kind of watcher on localStorage. It won't be updated until the component is initialised again, and initialValue is retrieved again.

In your use case, you need to actually use the same ref in both components. Do this in the usual Vue way by passing it as a prop, injecting it, or exporting the ref from a composable .js/.ts file.

@JEK58
Copy link
Author

JEK58 commented May 17, 2022

Thanks for your reply.
Regarding the watcher: If I remove the value from localStorage it gets immediately updated, so isn't there a watcher?

Also, if you open this link in two separate windows the changes are visible immediately with localStorage acting as a single source of truth: https://vueuse.org/core/usestorage/#demo

This is why I do not understand that it does not work in my case.

@meteorlxy
Copy link
Contributor

meteorlxy commented Aug 22, 2022

Also, if you open this link in two separate windows the changes are visible immediately with localStorage acting as a single source of truth

Yes, that's really confusing. See the demo below, it will sync when update the value in different windows, but won't get synced within the same one.

vueuse-use-storage

@antfu antfu added the bug Something isn't working label Aug 23, 2022
@suienzan
Copy link

suienzan commented Sep 6, 2022

Seems to be the limitation from storage event.

@xiziliang
Copy link

I had the same problem. If use prop, the flexibility is reduced

@henrycunh
Copy link

any way around this?

@davidmyersdev
Copy link

Thanks so much for fixing this, @antfu! Now I can delete around a dozen provide/inject calls. 🎉

@bgrand-ch
Copy link

bgrand-ch commented Dec 20, 2023

Hello, the @antfu patch no longer seems to be working 🤔

Example with Nuxt 3.8.2 and VueUse 10.7.0

./app.vue

<template>
  <h1>App</h1>
</template>

<script setup lang="ts">
import { StorageSerializers } from '@vueuse/core'
import type { UseStorageOptions } from '@vueuse/core'

const localStorageOpts: UseStorageOptions<any> = {
  serializer: StorageSerializers.object
}
const localValue = useLocalStorage<object|null>('localValue', null, localStorageOpts)

onBeforeMount(() => {
  console.log('app')

  localValue.value = {
    prop1: 'value1',
    prop2: 'value2'
  }

  console.log('localValue', localValue.value) // ok (object)
})
</script>

./pages/folder/index.vue

<template>
  <h1>Page</h1>
</template>

<script setup lang="ts">
import { StorageSerializers } from '@vueuse/core'
import type { UseStorageOptions } from '@vueuse/core'

const localStorageOpts: UseStorageOptions<any> = {
  serializer: StorageSerializers.object
}
const localValue = useLocalStorage<object|null>('localValue', null, localStorageOpts)

onBeforeMount(() => {
  console.log('page')
  console.log('localValue', localValue.value) // not ok (null instead object)
})
</script>

Dev console:

  • app
  • localValue { prop1: 'value1', prop2: 'value2' }
  • page
  • localValue null

@tutuca
Copy link

tutuca commented Oct 5, 2024

I'm hitting this bug replacing a reactive object I'm using as state store. The reactivity is lost when using useStorage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
10 participants