Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/toyobayashi/pinia-core


https://github.com/toyobayashi/pinia-core

Last synced: 2 days ago
JSON representation

Awesome Lists containing this project

README

        

# Use 🍍 in React

```bash
npm install @vue/runtime-core pinia-core
```

Example:

```ts
import { useRef, useCallback, useSyncExternalStore } from 'react'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import type { Plugin, InjectionKey, App } from '@vue/runtime-core'
import { Store, createPinia, defineStore } from 'pinia-core'
import type { PiniaPlugin } from 'pinia-core'

class SnapshotSaver {
private _store: S
private _selector?: (store: S) => unknown
public getSnapshot: () => unknown
public updateSnapshot: () => void

public constructor (store: S, selector?: (store: S) => unknown) {
this._store = store
this._selector = selector

let snapshot: unknown
this.getSnapshot = () => snapshot
this.updateSnapshot = () => {
const { _store, _selector } = this
snapshot = _selector ? _selector(_store) : new Proxy(_store, {})
}

this.updateSnapshot()
}

public tryUpdate (store: S, selector: ((store: S) => unknown) | undefined) {
const prevStore = this._store
const prevSelector = this._selector
const newStore = !Object.is(store, prevStore)
const newSelector = !Object.is(selector, prevSelector)
if (newStore) this._store = store
if (newSelector) this._selector = selector
if (newStore || newSelector) {
this.updateSnapshot()
}
}
}

function usePiniaStore<
S extends { $subscribe: (cb: (...args: unknown[]) => unknown) => () => void },
T = S
> (
store: S,
selector?: (store: S) => T
): T {
const snap = useRef>(null!)
if (!snap.current) {
snap.current = new SnapshotSaver(store, selector)
} else {
snap.current.tryUpdate(store, selector)
}

const subscribe = useCallback((onStoreChange: () => void) => {
return store.$subscribe(() => {
snap.current.updateSnapshot()
onStoreChange()
})
}, [store])

return useSyncExternalStore(subscribe, snap.current.getSnapshot as () => T)
}

interface FakeApp {
config: {
globalProperties: Record
};
use(plugin: Plugin): this;
provide(key: InjectionKey | string, value: T): this;
}

// for plugin
const fakeVueApp: FakeApp = {
provide () {
return this
},
config: {
globalProperties: {}
},
use (plugin) {
if (typeof plugin === 'function') {
plugin(this as App)
} else {
plugin.install(this as App)
}
return this
}
}

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate as unknown as PiniaPlugin)
fakeVueApp.use(pinia)

declare module 'pinia-core' {
interface DefineStoreOptions<
Id extends string,
S extends StateTree,
G,
A
> extends DefineStoreOptionsBase> {
persist: boolean
}
}

const mainStore = defineStore('main_store', {
persist: true,
state: () => {
return {
count: 0
}
},
actions: {
addCount () {
this.count++
}
}
})(pinia)

export default function Component () {
// connect store
const store = usePiniaStore(mainStore)

// with selector
const storeCount = usePiniaStore(mainStore, (state) => state.count)

// ...
}
```