Quantcast
Channel: Active questions tagged svelte - Stack Overflow
Viewing all articles
Browse latest Browse all 1541

Is this the right way to create a Svelte 5 store with two-way binding to a Firebase Realtime db path?

$
0
0

This is how I used to do it in Svelte 4:

// $lib/firebase.tsexport function writableRealtimeStore<T>() {  let unsubscribe: () => void = () => {}  let objectRef: any  const store = writable<T | null>(null)  let storeSet = store.set  return {    subscribe: store.subscribe,    set: (value: any) => {      return set(objectRef, value)    },    update: () => {},    setPath: (path: string) => {      objectRef = ref(realtimeDB, path)      unsubscribe()      unsubscribe = onValue(objectRef, (snapshot) => {        storeSet((snapshot.val() as T) ?? null)      })    },  }}// $lib/stores.tsexport const myStore = writableRealtimeStore()// routes/+page.svelte<script lang="ts">    import { myStore } from '$lib/stores'    myStore.setPath('/books/<book_id>')</script><input type="text" bind:value={myStore.bookName}

This store is reactive both ways - when the value in the DB changes, it updates the UI, and when the user updates the value of the input, the DB changes. I could access the properties of my DB object directly as myStore.bookName.

However with Svelte 5 I can't get the same behavior of the store object:

// $lib/firebase.tsexport function createRealtimeStore<T>() {    let unsubscribe = () => {}    let store: { value: T | undefined } = $state({ value: undefined })    let _ref: DatabaseReference    return {        get value(): T | undefined {            return store.value        },        update: () => {            if (_ref) set(_ref, store.value)        },        setPath: (path: string) => {            _ref = ref(realtime, path)            unsubscribe()            unsubscribe = onValue(_ref, (snapshot) => {                store.value = snapshot.val()            })        },        unsubscribe,    }}// $lib/stores.tsexport let myStore = createRealtimeStore()// routes/+page.svelte<script lang="ts">    import { myStore } from '$lib/stores'    myStore.setPath('/books/<book_id>')    $effect(() => {        if (myStore.value) {            myStore.update()        }    })</script><input type="text" bind:value={myStore.value.bookName}

Two problems:

  1. I must access the store's props like myStore.value.bookName, instead of the cleaner myStore.bookName.
  2. The $effect rune must be in the page and not in the function that creates the store, because $effect can only be called during component initialization, otherwise you get an error.

Overall the Svelte 4 way of doing it was much cleaner and nice to work with and I refuse to believe that you can't do the same thing with the new and supposedly improved store system.


Viewing all articles
Browse latest Browse all 1541

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>