如何在 Svelte 中创建一个可在所有页面中使用的上下文?
How to create a context that can be used in all pages in Svelte?
我目前正在学习 Svelte,我想为这个副项目创建一个身份验证流程。通常,在 React 中,我习惯使用 Contexts 保存身份验证信息。
<AuthContext>
<App />
<AuthContext>
我想知道 Svelte 是否也可以执行类似的方法?所有教程都是基于组件的上下文。我想在我的整个应用程序中调用 getContext('authContext')。
AuthContext.svelte
<script lang='ts'>
import { writable } from 'svelte/store'
import { onDestroy, setContext } from 'svelte'
import {getAuth, type User, onAuthStateChanged} from 'firebase/auth'
const auth = getAuth()
const userStore = writable<User | null>(null)
const isLoggedIn = writable<boolean>(false)
const contexts = {
isLoggedIn,
userStore,
logOut,
}
const unsubscribe = onAuthStateChanged(auth, (user) => {
if(user) {
userStore.set(user)
isLoggedIn.set(true)
}
})
setContext('authContext', contexts)
function logOut() {
auth.signOut()
isLoggedIn.set(false)
}
onDestroy(() => unsubscribe())
</script>
我在 __layout.svelte 中调用了 getContext:
<script lang='ts'>
import {getContext} from 'svelte'
const {isLoggedIn} = getContext('authContext')
</script>
它产生这个错误:
Cannot destructure property 'isLoggedIn'
of '__vite_ssr_import_1__.getContext(...)'
as it is undefined.
不确定这是否必须通过 SvelteKit 中的组件来完成?上下文不能这样构建和设置吗? REPL
(我过去常常在没有上下文的情况下这样做 REPL)
App.svelte
<script>
import { setContext } from 'svelte'
import {authContext} from './authContext'
import Component from './Component.svelte'
setContext('authContext', authContext)
</script>
<Component />
authContext.js
import { writable } from 'svelte/store'
import {getAuth, onAuthStateChanged} from 'firebase/auth'
const auth = getAuth()
const userStore = writable(null)
const isLoggedIn = writable(false)
onAuthStateChanged(auth, (user) => {
if(user) {
userStore.set(user)
isLoggedIn.set(true)
}else {
userStore.set(null)
isLoggedIn.set(false)
}
})
async function logOut() {
await auth.signOut()
// isLoggedIn.set(false) // (would handle via onAuthStateChanged)
}
export const authContext = {
isLoggedIn,
userStore,
logOut,
}
Component.svelte
<script>
import {getContext} from 'svelte'
const {isLoggedIn, userStore, logOut} = getContext('authContext')
async function handleLogout(){
try{
await logOut()
}catch(error){
console.error(error)
}
}
</script>
<div>
isLoggedIn: {$isLoggedIn}<br>
username:
{#if $isLoggedIn}
{$userStore.username}
{/if}
</div>
<button on:click={handleLogout}>
logOut
</button>
<style>
button {
margin-top: 1rem;
}
</style>
要在所有页面中使用'context',您应该只使用普通商店。
在外部 javascript 文件中定义商店:
// ./stores.js
import { writable } from 'svelte/store';
export const loggedIn = writable(false);
export const user = writable(null);
并在必要时简单地导入它:
<!-- Component.svelte -->
<script>
import { loggedIn } from './stores.js';
</script>
我目前正在学习 Svelte,我想为这个副项目创建一个身份验证流程。通常,在 React 中,我习惯使用 Contexts 保存身份验证信息。
<AuthContext>
<App />
<AuthContext>
我想知道 Svelte 是否也可以执行类似的方法?所有教程都是基于组件的上下文。我想在我的整个应用程序中调用 getContext('authContext')。
AuthContext.svelte
<script lang='ts'>
import { writable } from 'svelte/store'
import { onDestroy, setContext } from 'svelte'
import {getAuth, type User, onAuthStateChanged} from 'firebase/auth'
const auth = getAuth()
const userStore = writable<User | null>(null)
const isLoggedIn = writable<boolean>(false)
const contexts = {
isLoggedIn,
userStore,
logOut,
}
const unsubscribe = onAuthStateChanged(auth, (user) => {
if(user) {
userStore.set(user)
isLoggedIn.set(true)
}
})
setContext('authContext', contexts)
function logOut() {
auth.signOut()
isLoggedIn.set(false)
}
onDestroy(() => unsubscribe())
</script>
我在 __layout.svelte 中调用了 getContext:
<script lang='ts'>
import {getContext} from 'svelte'
const {isLoggedIn} = getContext('authContext')
</script>
它产生这个错误:
Cannot destructure property
'isLoggedIn'
of'__vite_ssr_import_1__.getContext(...)'
as it is undefined.
不确定这是否必须通过 SvelteKit 中的组件来完成?上下文不能这样构建和设置吗? REPL
(我过去常常在没有上下文的情况下这样做 REPL)
App.svelte
<script>
import { setContext } from 'svelte'
import {authContext} from './authContext'
import Component from './Component.svelte'
setContext('authContext', authContext)
</script>
<Component />
authContext.js
import { writable } from 'svelte/store'
import {getAuth, onAuthStateChanged} from 'firebase/auth'
const auth = getAuth()
const userStore = writable(null)
const isLoggedIn = writable(false)
onAuthStateChanged(auth, (user) => {
if(user) {
userStore.set(user)
isLoggedIn.set(true)
}else {
userStore.set(null)
isLoggedIn.set(false)
}
})
async function logOut() {
await auth.signOut()
// isLoggedIn.set(false) // (would handle via onAuthStateChanged)
}
export const authContext = {
isLoggedIn,
userStore,
logOut,
}
Component.svelte
<script>
import {getContext} from 'svelte'
const {isLoggedIn, userStore, logOut} = getContext('authContext')
async function handleLogout(){
try{
await logOut()
}catch(error){
console.error(error)
}
}
</script>
<div>
isLoggedIn: {$isLoggedIn}<br>
username:
{#if $isLoggedIn}
{$userStore.username}
{/if}
</div>
<button on:click={handleLogout}>
logOut
</button>
<style>
button {
margin-top: 1rem;
}
</style>
要在所有页面中使用'context',您应该只使用普通商店。
在外部 javascript 文件中定义商店:
// ./stores.js
import { writable } from 'svelte/store';
export const loggedIn = writable(false);
export const user = writable(null);
并在必要时简单地导入它:
<!-- Component.svelte -->
<script>
import { loggedIn } from './stores.js';
</script>