Skip to content

Instantly share code, notes, and snippets.

@monsat
Created October 30, 2022 05:50
Show Gist options
  • Save monsat/c6b8a5bf0e8ba360086b82bef4c7ea9f to your computer and use it in GitHub Desktop.
Save monsat/c6b8a5bf0e8ba360086b82bef4c7ea9f to your computer and use it in GitHub Desktop.
Add commit/restore storage method to Vue.js global state Ref
import { ref } from 'vue-demi'
import type { Ref, UnwrapRef } from 'vue-demi'
import { createGlobalState, useSessionStorage } from '@vueuse/core'
export type StorableRef<T> = Ref<T> & {
commit: () => void
restore: () => void
}
const createState = <T>(storageKey: string, initialValue: T) => createGlobalState(() => useSessionStorage(storageKey, initialValue))
export function storableRef<T>(storageKey: string, initialValue: T): StorableRef<T> {
const actual = ref(initialValue) as Ref<T>
const stored = createState<T>(storageKey, initialValue)()
const commit = () => {
stored.value = actual.value
}
const restore = () => {
actual.value = stored.value
}
Object.defineProperties(actual, {
commit: {
value: commit,
},
restore: {
value: restore,
},
})
// read from storage on mount
restore()
return actual as StorableRef<T>
}
@monsat
Copy link
Author

monsat commented Oct 30, 2022

Usage:

<script setup>
const name = storableRef('')
const save = async () => {
  await saveForDatabase()
  name.commit()
}
const reset = () => name.restore()
</script>
<template>
  <div>
    <input v-model="name" />
    <button @click="reset">Reset</button>
  </div>
</template>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment