@uni-store/core

Unified Store. You can use @uni-store/core with Vue or React fornow.

Usage no npm install needed!

<script type="module">
  import uniStoreCore from 'https://cdn.skypack.dev/@uni-store/core';
</script>

README

@uni-store/core npm build status coverage

Unified Store. You can use @uni-store/core with Vue or React fornow.

Based on @vue/reactivity and watch with @vue/runtime-core.

Inspired by Pinia.

Installation

pnpm add @uni-store/core
# or with yarn
yarn add @uni-store/core
# or with npm
npm install @uni-store/core

Usage

Create a Store

You can create as many stores as you want:

// src/stores/counter
import { defineStore, ref, computed } from '@uni-store/core'

export const useCounter = defineStore(() => {
  const n = ref(0)
  const increment = (amount = 1) => {
    n.value += amount
  }

  const computedN = computed(() => {
    return n.value + 100
  })

  return {
    n,
    increment,
    computedN
  }
})

defineStore returns a function that has to be called to get access to the store:

import { nextTick, computed } from '@uni-store/core'
import { useCounter } from '@/stores/counter'

const counter = useCounter()
const stateN = computed(() => {
  return counter.n
})

let calledTimes = 0
// subscribe state change
counter.$subscribe((newState) => {
  calledTimes += 1
  expect(newState.n).toEqual(stateN.value)
})

expect(counter.n).toEqual(0)
expect(counter.computedN).toEqual(100)
expect(stateN.value).toEqual(0)
expect(calledTimes).toEqual(0)

counter.increment()
expect(counter.n).toEqual(1)
expect(counter.computedN).toEqual(101)
expect(stateN.value).toEqual(1)

nextTick(() => {
  expect(calledTimes).toEqual(1)
  counter.increment(10)
  expect(counter.n).toEqual(11)
  expect(counter.computedN).toEqual(111)
  expect(stateN.value).toEqual(11)
  nextTick(() => {
    expect(calledTimes).toEqual(2)
  })
})

With Vue 3

import { defineComponent } from 'vue'
export default defineComponent({
  setup () {
    const counter = useCounter()
    // but you can not do like this:
    // const { n } = counter
    // it breaks reactivity
    return {
      counter
    }
  }
})

Documentation

First of all, you need to read:

@uni-store/core export all @vue/reactivity API by default.

You can use all Vue reactivity API. Includes the following API from @vue/runtime-core:

Define Store

A Store is defined using defineStore() API, just like Vue setup:

// @/stores/counter
import { defineStore, ref } from '@uni-store/core'

export const useStore = defineStore(() => {
  const n = ref(1)
  const increment = (amount = 1) => {
    n.value += amount
  }

  return {
    n,
    increment
  }
})

Now you can get a custum useStore. Also you can rename it to other variable name, like useCounter.

Use Store

The store won't be created until useStore() is called:

import { useStore } from '@/stores/counter'

const store = useStore()

// you can use the states:
console.log(store.n) // should log 1

// increment n, amount = 10
store.increment(10)

console.log(store.n) // should log 11

You can even get another store instance in some special cases:

const anotherStore = useStore(true)

console.log(anotherStore.n) // should log 1
Subscribing state
// subscribe state change
store.$subscribe((state) => {
  // keep the whole state to local storage whenever it changes
  localStorage.setItem('cart', JSON.stringify(state))
})

License

MIT