vue-immer-state

1.0.4 • Public • Published

vue-immer-state

Purpose

vue-immer-state is a minimalistic approach for state management in Vue using immer.

Description

A State - in the sense of this library - is comprised of a reference to an immutable value, together with a method named commit to allow for changes to the value.

type State<T> = DeepReadonly<{
    ref: Ref<T>
    commit?: (updater: (value: T) => void) => void
}>

Let's begin with a simple example, how you would define the state of a User model:

import { createState } from 'vue-immer-state'

type User = { name: string }

const userState = createState<User>({ name: 'Foo' })

You can mutate its value by committing an update-method:

// before
console.log(userState.ref.value.name)
> 'Foo'

userState.commit?.(
    (user) => { user.name = 'Bar' }
)

// after
console.log(userState.ref.value.name)
> 'Bar'

For any details on how update-methods work, please take a look at the documentation of the great immer project: https://immerjs.github.io/immer/

If you define your state as readonly, or if you pass a readonly reference, createState will not provide you with a commit-method:

const userState = createState<User>(
  computed(() => appState.ref.value.user)
)

// or
const userState = createState<User>({ name: 'Foo' }, **true**)

// before
console.log(userState.ref.value.name)
> 'Foo'

// this has no effect
userState.commit?.(
    (user) => { user.name = 'Bar' }
)

// after
console.log(userState.ref.value.name)
> 'Foo'

Let's take a look at a more complex example and derive a User state from an App state:

import { createState } from 'vue-immer-state'

type User = { name: string }
type App  = { user: User }

const appState = createState<App>(
  { user: { name: 'Foo' } }
)

const userState = createState<User>(
  computed({
    get () { 
      return appState.ref.value.user 
    },
    set (value) { 
      appState.commit?.((app) => { app.user = value }) 
    }
  })
)

Now, whenever we commit changes to the User state, this in turn updates the App state instead. The changes then trickle down again to the reactive User state.

// before
console.log(userState.ref.value.name)
> 'Foo'
console.log(appState.ref.value.user.name)
> 'Foo'

userState.commit?.(
    (user) => { user.name = 'Bar' }
)

// after
console.log(userState.ref.value.name)
> 'Bar'
console.log(appState.ref.value.user.name)
> 'Bar'

For states to work as prop values, you need to define your components properties as such:

<script setup lang="ts">
  const { userState } = defineProps<{
    userState: State<User>
  }>()

  // extract the ref for template usage
  const user = userState.ref
</script>

<template>
  <div>User {{ user.name }}</div>
</template>

Now passing state is straightforward:

<User :user-state="userState" />

Installation

Use npm or yarn to install:

> npm i ntrpy/vue-immer-state

or 

> yarn add ntrpy/vue-immer-state

Have fun!

Package Sidebar

Install

npm i vue-immer-state

Weekly Downloads

1

Version

1.0.4

License

MIT

Unpacked Size

7.32 kB

Total Files

6

Last publish

Collaborators

  • ntrpy