use Redux with Svelte ๐
qaynam
Posted on June 13, 2024
I've been developing a product fully utilizing SvelteKit, and while server-side tests can be handled directly with Jest, unit testing on the client side can't be done just by adding Jest. Support for ESM needs to be added in various ways, it would be fine to break down logic into smaller functions for testing, but that makes the code a bit cumbersome to manage, and I also wanted to test changes in state, which was the start of it all.
Benefits I've considered by deciding on Redux:
- Makes it easier to transition to a different framework in the future
- Less affected when updating from v4 to v5
- Improves maintainability
Disadvantages I've considered:
- Increases the amount of code
- Requires various adjustments to operate in Svelte
Here is a rough code snippet like below๐
Store.redux.ts
import { configureStore, createSlice } from '@reduxjs/toolkit';
export interface MenuFormStore {
name: string;
}
const initialState: MenuFormStore = {
name: '',
};
const menuFormSlice = createSlice({
name: 'menuForm',
initialState,
reducers: {
setName: (state, action: { payload: string }) => {
state.name = action.payload;
}
}
});
const MenuFormActions = menuFormSlice.actions;
const menuFormStoreRedux = configureStore({
reducer: menuFormSlice.reducer
});
const MenuFormDispatch = menuFormStoreRedux.dispatch;
export const MenuFormReduxStoreModule = {
initialState,
Actions: MenuFormActions,
Store: menuFormStoreRedux,
Dispatch: MenuFormDispatch
} as const;
This file has nothing to do with Svelte, so you can write unit tests directly with Jest.
However, this alone does not make it reactive on Svelte, so we define a read-only store in a separate file using readonly
from svelte/store
like below (placing it in the same file will anger Jest)
Store.ts
import { onMount } from 'svelte';
import { writable, readonly } from 'svelte/store';
import { MenuFormReduxStoreModule } from './MenuForm.redux';
const state = writable(MenuFormReduxStoreModule.initialState);
export const getMenuFormStore = () => {
onMount(() =>
MenuFormReduxStoreModule.Store.subscribe(() => {
state.update(prev => ({ ...prev, ...MenuFormReduxStoreModule.Store.getState() }));
})
);
return readonly(state);
};
Usage within Svelte would be as below๐
Menu.svelte
<script lang="ts">
import { getMenuFormStore } from './Store';
import { MenuFormReduxStoreModule } from './Store.redux';
$: menuFormStore = getMenuFormStore();
const { Actions, Dispatch } = MenuFormReduxStoreModule;
</script>
<div>
{$menuFormStore.name}
<input on:input={e => Dispatch(Actions.setName(e.currentTarget.value))}/>
</div>
In Conclusion
Likely the same system could be used for jotai or zustand, which is appreciated since many issues are resolved in Svelte v5.
Posted on June 13, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.