Skip to content

Immutable store for Svelte with full Typescript support and Redux Devtools integration.

License

Notifications You must be signed in to change notification settings

endenwer/svelte-restate

Repository files navigation

Svelte Restate

Immutable store for Svelte with full Typescript support and Redux Devtools integration. It is highly inspired by re-frame subscriptions(read more about signal graph and subscription layers here). Immer is used to work with immutable state.

Install

npm i svelte-restate --save

Usage [Demo]

Create store with initial state.

import { createStore } from 'svelte-restate'

export interface State {
  isLoading
  todos: {
    id: number
    completed: boolean
    description: string
  }[]
}

const initState: State = {
  isLoading: true,
  todos: []
}

export default createStore(initState)

Create subscriptions. See more examples in documentation for RegRootsub and RegSub.

import store from './store'

// register root subs
const isLoading = store.regRootSub(
  'isLoading',
  ($root) => $root.count
)

const todos = store.regRootSub(
  'todos',
  ($root) => $root.todos
)

// use root subs to register derived subs
const completedTodos = store.regSub(
  'completedTodos',
  () => todos()
  ($todos) => $todos.filter(todo => todo.completed)
)

// register sub with arguments
const todo = store.regSub(
  'todo',
  () => todos()
  ($todos, [id]: [number]) => $todos.find(todo => todo.id === id)
)

export default { count }

Create mutations. See more examples in documentation for RegMut.

import store from './store'

const setLoading = store.regMut<boolean>(
  'setLoading',
  (draft, value) => draft.isLoading = value
)

const insertTodos = store.RegMut<Todo[]>(
  'insertTodos',
  (draft, todos) => draft.todos = todos
)

export default { setLoading, insertTodos }

Use in svelte component.

<script>
  import muts from './muts'
  import subs from './subs'
  import store from './store'
  import { onMount } 'svelete'
  import { fetchTodos } './api'

  // subscription without arguments.
  // To get the value use '$isLoading'
  const isLoading = subs.isLoading()

  // subscription with arguments
  export let id: number
  $: todo = subs.todo(id)

  // use mutations
  onMount(async () => {
   muts.setLoading(true)
   const todos = await fetchTodos()

   // call multiple mutations within transaction
   store.transaction(tx => [
     muts.setIsLoading(false, tx),
     muts.insertTodos(todos, tx)
   ])
  })
</script>

{# if $isLoading}
  <div>Loading...</div>
{:else}
  <div>{$todo.description}</div>
{/if}

Connect to Redux devtools. You can see main state, state of all active subscriptions and dispatch mutations directly from the devtools. Time travel also works. See documentation for connectToDevtools.

import muts from './muts'
import store from './store'

connectToDevTools(store, muts)