vuex-apiaction v2.3.1
Vuex API action
A simple decorator to define actions that lazily and automatically populate your state from a remote API.
This is an extension of vuex-class-component.
Usage
Here is a quick example:
import { createModule, mutation, action } from 'vuex-class-component'
import { apiAction, ApiValue } from 'vuex-apiaction'
const VuexModule = createModule()
interface User {
firstname: string
lastname: string
age: number
}
interface UserState {
users: ApiValue<User[]>
}
class UserStore extends VuexModule.with({ namespaced: 'user/', strict: false }) implements UserState {
users = new ApiValue<User[]>()
@apiAction({ name: 'users', defaultValue: [] as User[] })
async loadUsers (): Promise<User[]> {
// Usually, you call a remote API endpoint, with Vue.axios or equivalent,
// and return a simple array of User
return [{
firstname: 'Michael',
lastname: 'Olofinjana',
age: 32
}, {
firstname: 'Ola',
lastname: 'Nordmann',
age: 28
}]
}
}The decorator @apiAction does the following:
- Hook up accessors to the member named
users(as defined by thenameparameter) to automatically callloadUsers()if the member is inUnsetstate - Store the returned value in the member, or error if any
Here is how it can be used in a Vue component using a proxy:
<template>
<div>
<div v-if="loading">
Users are loading, please wait
</div>
<div v-else>
Users are {{ investigations.map(i => i.id).join(', ') }}
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { vxm } from '@/store'
import { isLoading, isOk } from 'vuex-apiaction'
@Component
export default class UserList extends Vue {
get loading () {
return isLoading(vxm.users.users)
}
get users () {
return isOk(vxm.users.users) ? vxm.users.users.value : []
}
}
</script>
<style>
</style>Note that we never call loadUsers manually, it is automatically called when needed.
Warning
Since Typescript 4.3, useDefineForClassFields is set to true if target is esnext, and this is for now incompatible with decorators.
This is not mentioned in release notes, as noticed on https://github.com/microsoft/TypeScript/issues/44673, https://github.com/microsoft/TypeScript/issues/44449 and https://github.com/microsoft/TypeScript/issues/34787#issuecomment-849379479
If your project use esnext, please be sure to set useDefineForClassFields: false. If you are also using private fields, it's not allowed, so you'll have to either:
- Stick on Typescript < 4.3
- Set a lower ES target
API
ApiValue helpers
reset- Reset the internal state of the value, so that a new access to it can trigger a reload
isUnset,isLoading,isFailure,isOk- User defined type guards, corresponding to each state of the value
update(value?: T | null, error?: Error)- Manually update the internal value. WARNING this has to be done inside a Vuex mutation.
wait- Async function that will return only when the loader finished.
apiAction
This decorator has to be used around a method within a Vuex class component. It takes the following parameters:
name: Name of the member it should update. This must be an instance (or declaration) ofApiValuedefautValue: Default value to be used when there is an errorsetter: Even less supported. This should be the name of a setter to be called after calls to the decorated function. Payload is{ value?: T | null, error?: Error }. Default to internal auto-managed setter.
apiLoader
This a function to create your own loader, without defining members. It is used by @apiAction. This is an advanced use-case.