vuex-apiaction
v2.3.1
Published
Minimal vuex action definition to autoload your state lazily from a remote API
Downloads
2
Maintainers
Readme
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 thename
parameter) to automatically callloadUsers()
if the member is inUnset
state - 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) ofApiValue
defautValue
: 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.