DEV Community

FRicardi
FRicardi

Posted on

Svelte - Where to go from here?

The basics

I was looking forward to learn a little bit about svelte, since i've heard a lot of fuzz on it on the last couple years. There was this college task to create a web project, and my group decided to do it with svelte.
At first, i was really thrilled with how easy it was to create new things and how fast the application was being built.
After finishing the MVP for the college discipline, i was left with some questions, which i would love to receive your inputs on, since i was kinda on a hurry developing this but would love to come back to it and code it properly! :)

How to properly extend components?

The first thing that struck me was how to properly extend components and leverage most of the structure. The project i've created contained some forms, and i was used to the pattern that consist on creating components for inputs so it is easier to add form group inputs to a form. On svelte, it seems that i'm not able to create a component like:

<script>
    export let type = 'text';
    export let label;
</script>
<div>
    <span>{label}</span>
    <input {type} />
</div>
Enter fullscreen mode Exit fullscreen mode

The error/warning i'm getting is that the type cannot be dynamic here. The approach I took, only to finish it quicker, was to create a component for each type i've had to use, which sounded bad. very bad. At this point it was easier to recreate the span/input structure on each input.

Authentication store and user

In order to save the bearer token used to prove authentication on the api calls, i've created a store using writable. To this project, i've created one for the authentication and other one to the user data. The user data one contains just the roles currently, just because i didn't need other informations so far. They looked like this:
auth.js

import user from './user';
import { writable } from 'svelte/store'
const { subscribe, set } = writable(localStorage.getItem('token'));

const logout = () => {
    set(null);
    localStorage.removeItem('token');
    user.resetUserRole();
}

const update = (newToken) => {
    localStorage.setItem('token', newToken);
    set(newToken);
    user.populateUserData();
}

export default {
    subscribe, logout, update
}
Enter fullscreen mode Exit fullscreen mode

user.js

import { writable } from 'svelte/store'
import auth from './auth'
import { userConnector } from '../backend-connector';

const { subscribe, set } = writable(localStorage.getItem('role'))

const resetUserRole = () => {
    set(null);
    localStorage.removeItem('role');
}

const updateUserRole = (newRole) => {
    localStorage.setItem('role', newRole);
    set(newRole);
}

const populateUserData = () => {
    userConnector.getUserData().then((response) => {
        if (response.ok) {
            response.json().then((data) => {
                updateUserRole(data.roles.map((role) => role.name));
            });
        } else {
            auth.logout();
        }
    }).catch(() => {
        auth.logout();
    });
}

export default {
    subscribe, resetUserRole, updateUserRole, populateUserData
}
Enter fullscreen mode Exit fullscreen mode

The .then() structure used instead of await was used just because i was teaching my colleague how a promise works and forgot to change to the classier await syntax, i know it looked lame hehe
The objective of the populateUserData method was to update user informations whenever they log in or enter the system, keeping them consistent with the localStorage so it is kept whenever the user quits the tab and enter again. Although i've liked the result, and using the svelte/store get method to read the content of any store was quite easy, i would like to know how you would place this structure!

Role guards on route

Since there isn't any platform component for that, I've tried to create a structure that represent guards to some route based on their role on the system. It looked like this:

<script>
    import { Route } from 'svelte-navigator';
    import auth from '../../store/auth';
    import user from '../../store/user';

    export let path;
    export let componentToRoleMapping;

    $: isAuthenticated = $auth;
    $: role = $user;
</script>

{#if isAuthenticated && componentToRoleMapping[role] != null}
    <Route path={path} component={componentToRoleMapping[role]} />
{:else}
    <Route path={path} component={componentToRoleMapping['ELSE']} />
{/if}
Enter fullscreen mode Exit fullscreen mode

And the componentToRoleMapping object looks like this:

let feedComponentToRoleMapping = {
     'DONOR': DonorFeed,
     'ADMIN': AdminFeed,
     'ELSE': Login
}
Enter fullscreen mode Exit fullscreen mode

Is there some way to improve this? it felt quite right but as if something is missing.

Final thoughts

Svelte was a nice framework to learn, i feel like there is a lot of room for improvement, but it was one of the easiest ways to code from zero to hero that i've found so far. Almost zero bureaucracy and a lot of shortcuts, i would love to work with it in the future. If you have any inputs on how to improve this code, and/or have some material to learn more about the technology, i would love to see that!

Discussion (6)

Collapse
tboss profile image
Travis

I know this is older now but I think you want to look at slots for your first issue: svelte.dev/docs#slot

Collapse
fricardi profile image
FRicardi Author

Nice! Thanks a lot, it indeed was one of the things I was looking for. Waiting for another college assignment or professional opportunity to get closer to this framework

Collapse
loopes_davi profile image
davi 🇵🇸

Nice article, congrats!!

Collapse
fricardi profile image
FRicardi Author

Thanks mate!

Collapse
andremzzr profile image
André Ribeiro

Great article, FRicardi!

Collapse
fricardi profile image
FRicardi Author

Thanks, André!