vuex-apiaction

2.3.1 • Public • Published

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 the name parameter) to automatically call loadUsers() if the member is in Unset 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) of ApiValue
  • defautValue: Default value to be used when there is an error
  • setter: 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.

Package Sidebar

Install

npm i vuex-apiaction

Weekly Downloads

5

Version

2.3.1

License

MIT

Unpacked Size

21.4 kB

Total Files

10

Last publish

Collaborators

  • glandos