I am trying to change component once the user is logged in, but so far I am not able to do this. Once I make successful login, component remains the same.
I have App.svelte component:
<script>
import { fade } from 'svelte/transition'
import { currentComponent } from './store/view.svelte';
const loadComponent = currentComponent()
$effect(() => {
console.log(loadComponent);
})
</script>
<div id="viewport" transition:fade>
<svelte:component this={loadComponent.component}></svelte:component>
</div>
Login.svelte component
<script>
import { currentComponent } from "../store/view.svelte";
let email = $state('')
let password = $state('')
let test = currentComponent()
/**
* @param {{ preventDefault: () => void; }} event
*/
async function submit(event){
event.preventDefault()
fetch('http://localhost:9555/api/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
email,
password
})
})
.then(resp => resp.json())
.then(json => {
localStorage.setItem('_token', json.token)
test.updateComponent()
})
}
</script>
<div
class="relative mx-auto w-full max-w-md bg-white px-6 pt-10 pb-8 shadow-xl ring-1 ring-gray-900/5 sm:rounded-xl sm:px-10">
<div class="w-full">
<div class="text-center">
<h1 class="text-3xl font-semibold text-gray-900">Sign in</h1>
<p class="mt-2 text-gray-500">Sign in below to access your account</p>
</div>
<div class="mt-5">
<form action="" onsubmit="{submit}">
<div class="relative mt-6">
<input
bind:value={email}
placeholder="Email Address"
class="peer mt-1 w-full border-b-2 border-gray-300 px-0 py-1 placeholder:text-transparent focus:border-gray-500 focus:outline-none"
autocomplete="NA" />
<label for="email" class="pointer-events-none absolute top-0 left-0 origin-left -translate-y-1/2 transform text-sm text-gray-800 opacity-75 transition-all duration-100 ease-in-out peer-placeholder-shown:top-1/2 peer-placeholder-shown:text-base peer-placeholder-shown:text-gray-500 peer-focus:top-0 peer-focus:pl-0 peer-focus:text-sm peer-focus:text-gray-800">Email Address</label>
</div>
<div class="relative mt-6">
<input type="password" name="password" id="password"
bind:value={password}
placeholder="Password" class="peer peer mt-1 w-full border-b-2 border-gray-300 px-0 py-1 placeholder:text-transparent focus:border-gray-500 focus:outline-none" />
<label for="password" class="pointer-events-none absolute top-0 left-0 origin-left -translate-y-1/2 transform text-sm text-gray-800 opacity-75 transition-all duration-100 ease-in-out peer-placeholder-shown:top-1/2 peer-placeholder-shown:text-base peer-placeholder-shown:text-gray-500 peer-focus:top-0 peer-focus:pl-0 peer-focus:text-sm peer-focus:text-gray-800">Password</label>
</div>
<div class="my-6">
<button type="submit" class="w-full rounded-md bg-black px-3 py-4 text-white focus:bg-gray-600 focus:outline-none">Sign in</button>
</div>
<p class="text-center text-sm text-gray-500">Don't have an account yet?
<a href="#!"
class="font-semibold text-gray-600 hover:underline focus:text-gray-800 focus:outline-none">Sign
up
</a>.
</p>
</form>
</div>
</div>
</div>
view.svelte.js:
import Restaurant from "../routes/Restaurant.svelte";
import Login from '../routes/Login.svelte';
export function currentComponent(){
const _token = localStorage.getItem('_token')
let authorized = $state(_token ? true : false)
let component = $derived(!authorized ? Login : Restaurant)
function updateComponent(){
authorized = true
}
return {
get authorized(){
return authorized
},
set authorized(newValue){
authorized = newValue
},
get component(){
return component
},
updateComponent
}
}
Once I update authorized (test.updateComponent() call), the component is updated in view.svelte.js but the new component is not rendered. What am I doing wrong here?
You are not changing the same instance, hence nothing happens.
You could e.g. do either of
Make
currentComponenta singleton, e.g.(Of course you then would not call
currentComponentany more.)Create one instance at the root component and pass that around, e.g. via a context.
Also, for the fade to work, you would need something like this: