Added plumbing for redux in svelte

This commit is contained in:
Caleb Owens 2024-11-18 15:36:17 +01:00
parent fb1d1703ed
commit 634ce90ea7
4 changed files with 87 additions and 0 deletions

View File

@ -0,0 +1,29 @@
import { selectSelf } from '$lib/redux/selectSelf';
import { createSelector, createSlice } from '@reduxjs/toolkit';
export interface ExampleState {
value: number;
}
const initialState: ExampleState = {
value: 0
};
const exampleSlice = createSlice({
name: 'example',
initialState,
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
}
}
});
export const { increment, decrement } = exampleSlice.actions;
export const exampleReducer = exampleSlice.reducer;
export const selectExample = createSelector(selectSelf, (state) => state.example);
export const selectExampleValue = createSelector(selectExample, (example) => example.value);

View File

@ -0,0 +1,5 @@
import type { RootState } from '$lib/redux/store';
export function selectSelf(state: RootState): RootState {
return state;
}

View File

@ -0,0 +1,17 @@
import { exampleReducer } from '$lib/redux/example';
import { configureStore } from '@reduxjs/toolkit';
/**
* The base store.
*
* This is a low level API and should not be used directly.
* @private
*/
export const _store = configureStore({
reducer: {
example: exampleReducer
}
});
export type RootState = ReturnType<typeof _store.getState>;
export type AppDispatch = typeof _store.dispatch;

View File

@ -0,0 +1,36 @@
import { _store, type AppDispatch, type RootState } from '$lib/redux/store';
import { derived, readable, type Readable } from 'svelte/store';
/**
* Used to access the store directly. It is recommended to access state via
* selectors as they are more efficient.
*/
export function useStore(): Readable<RootState> {
const stateStore = readable(_store.getState(), (set) => {
const unsubscribe = _store.subscribe(() => {
set(_store.getState());
});
return unsubscribe;
});
return stateStore;
}
/**
* Used in combination with slice specific selectors. If an argument of the
* selector depends on a reactive property, IE something defined with
* `$state` or similar runes, then the `useSelector` call should be wrapped in
* a `$derived` block.
*/
export function useSelector<T>(selector: (state: RootState) => T): Readable<T> {
const stateStore = useStore();
return derived(stateStore, (state) => selector(state));
}
/**
* Used to access the dispatch function.
*/
export function useDispatch(): AppDispatch {
return _store.dispatch;
}