@wowissu/vux
v1.1.14
Published
Use Composition API to imitate Vuex in Vue3.
Downloads
6
Readme
@wowissu/vux
Like Vuex, but base on Vue3 composition API.
import { reactive } from 'vue';
export function createStore(
stateCaller: () => reactive({ [key: string]: any }),
getterCaller: ({state}) => { [key: string]: any },
mutateCaller: ({state, getter}) => { [key: string]: () => void },
actionCaller: ({state, getter, mutate}) => { [key: string]: () => any }
)
StateCaller()
must returnreactive({ ... })
GetterCaller()
recommand return thecomputed(() => 'your getter')
.MutateCaller()
state is only writable in mutate methods.ActionCaller()
the state or mutate both readonly in action methods, call mutate method for change the state.
How to use
// foo.store.ts
import { reactive, computed } from 'vue';
import { createStore } from '@wowissu/vux';
export const store = createStore(
// state caller
() => reactive({
foo: false
}),
// getter caller
({ state }) => ({
reverseFoo: computed(() => !state.foo)
}),
// mutate caller
({ state, getter }) => ({
setFoo(bar: boolean) {
state.foo = bar;
}
}),
// action caller
({ state, mutate, getter }) => ({
doAction() {
mutate.setFoo(!state.foo)
}
})
)
Dynamic make store
Initialize the store only the first time when useStore()
is called, and return the same one at other times
// foo.store.ts
import { reactive, computed } from 'vue';
import { createStore } from '@wowissu/vux';
const makeStore = () => createStore(
// ... as above ...
)
let store!: ReturnType<typeof makeStore>
export const useStore() {
return store ??= makeStore()
}
In Vue
import { useStore } from 'foo.store.ts';
export default defineComponent({
// ...
setup () {
const { state, getter } = useStore();
// use computed to watch data
const foo = computed(() => state.foo)
// or return the getter which already wrap by computed
const reverseFoo = getter.reverseFoo
return { foo, reverseFoo }
}
})
Separate
If like all separate. try below.
📦bar
┣ 📜action.ts
┣ 📜getter.ts
┣ 📜index.ts
┣ 📜mutate.ts
┗ 📜state.ts
// bar/index.ts
import { createStore } from '@wowissu/vux';
import { stateCaller } from './state';
import { getterCaller } from './getter';
import { mutateCaller } from './mutate';
import { actionCaller } from './action';
const genStore = () => createStore(
stateCaller,
getterCaller,
mutateCaller,
actionCaller
);
// store into memory
let store!: ReturnType<typeof genStore>
// export
export const useBarStore = () => {
return store ??= genStore();
}
// bar/state.ts
import { reactive } from 'vue'
export type State = ReturnType<typeof stateCaller>;
export const stateCaller = () => reactive({
foo: false
});
// bar/getter.ts
import { computed } from 'vue';
import { GetterContext } from '@wowissu/vux';
import { State } from './state';
export type Getter = ReturnType<typeof getterCaller>;
export const getterCaller = ({ state }: GetterContext<State>) => ({
reverseFoo: computed(() => !state.foo)
});
// bar/mutate.ts
import { MutateContext } from '@wowissu/vux';
import { Getter } from './getter';
import { State } from './state';
export type Mutate = ReturnType<typeof mutateCaller>;
export const mutateCaller = ({ state }: MutateContext<State, Getter>) => ({
setFoo(val: boolean) {
state.foo = val;
}
});
// bar/action.ts
import { ActionContext } from '@wowissu/vux';
import { Getter } from './getter';
import { Mutate } from './mutate';
import { State } from './state';
export const actionCaller = ({ state, mutate }: ActionContext<State, Getter, Mutate>) => ({
toggleFoo () {
mutate.setFoo(!state.foo)
}
});
:warning: Async Store
:warning: Async stateCaller is unrecommended. should consider to use async Action method for fetch data and change the state via mutate at first.
Fetch the data before init state.
createStore(
// async state caller
async () => {
const data = await fetchSomeData();
return reactive({
data
})
}
)
Use in async vue
If you want use Async Component, please wrap with <suspebnse /> component.
import { computed } from 'vue';
import { useStore } from 'store.ts';
export default defineComponent({
// ...
async setup () {
const { state, action } = await useStore();
const foo = computed(() => state.foo)
return { foo }
}
})