如何使用Firebase的onSnapshot在Svelte中创建响应式语句?

kupeojn6  于 2023-10-22  发布在  其他
关注(0)|答案(2)|浏览(118)

我在过去的4天里一直在学习Svelte,我正试图将其与Firebase集成。
我需要听一个文件命名的用户的uid后,用户登录,我保存在一个可写的名称userStore。

  • 注意:我的背景是React,这可以通过useEffect轻松完成 *

我需要一种方法来调用unsubscribe在onDestroy语句.我怎么能这么做呢?

onDestroy(() => {
        unsubscribe();
    });

这是我现在的代码:

$: if ($userStore)
        onSnapshot(doc(db, 'userInfo', $userStore.uid), (doc) => {
            if (doc.data()) {
                console.log(doc.data());
                userInfoStore.set(doc.data() as UserInfo);
            }
        });
jjjwad0x

jjjwad0x1#

我认为onSnapshot()返回unsubscribe,所以它应该像这样工作

<script>

    let unsubscribe

    onDestroy(() => {
        if(unsubscribe) unsubscribe();
    });

    $: if ($userStore) {
        unsubscribe =  onSnapshot(doc(db, 'userInfo', $userStore.uid), (doc) => {
            if (doc.data()) {
                console.log(doc.data());
                userInfoStore.set(doc.data() as UserInfo);
            }
        });
    }

</script>

用户注销时组件是否被销毁?因为如果用户注销,应该调用取消订阅?我认为在一个组件中可能不是处理逻辑的最佳位置。这将是一种通过定制商店

userInfoStore.js

export const userInfoStore = (() => {
        const initialValue = {}
        const {subscribe, set} = writable(initialValue)

        let unsubSnapshot

        return {
            subscribe,

            startListener(uid) {
                unsubSnapshot = onSnapshot(doc(db, 'userInfo', uid), (doc) => {
                    if (doc.data()) {
                        console.log(doc.data());
                        set(doc.data() as UserInfo);
                    }
                });
            },

            stopListener() {
                if(unsubSnapshot) unsubSnapshot()
            }
        }
    })();

auth.js

onAuthStateChanged(auth, user => {
        if(user) {
            userStore.set(user)
            userInfoStore.startListener(user.uid)
        }else {
            userInfoStore.stopListener()
        }
    })

App.svelte(主组件)

不知道这有多重要,或者当页面关闭时侦听器是否停止

<script>
import {onDestroy} from 'svelte'
import {userInfoStore} './userInfoStore'

 onDestroy(() => {
        userInfoStore.stopListener()
    });
</script>
jbose2ul

jbose2ul2#

Svelte宣布了Runes for v5,以下是如何实现它:

export function createUser() {
  let user = $state(null)

  function setUser(value) {
    user = value
  }

  return {
    // We need to use a getter here or the value will always be
    // whatever it is at the time function was called.
    get user() {
      return user
    },
    setUser
  }
}

export function createFirestore() {
  const data = createUser()
  let unsubscribe

  $effect(() => {
    if (data.user) {
        unsubscribe = onSnapshot(doc(db, 'userInfo', data.user.uid), (doc) => {
          data.setUser(doc.data())
        });
    }

    return () => {
        unsubscribe?.()
    }
  })

  return {
    get user() {
      return data.user
    },
  }
}

然后将这些函数导入到您的svelte组件中:

<script>
import { createUserFirestore } from './yourFunctions'

const data = createUserFirestore()
</script>

<User user={data.user} />

当然,您可以在组件内部执行所有这些逻辑。
请注意,Svelte v5尚未发布,将有变化,但只是想把它留在这里供将来参考。

相关问题