query-machine
    TypeScript icon, indicating that this package has built-in type declarations

    1.5.1 • Public • Published


    XState
    A combination of XState and Axios

    npm version

    query-machine is a combination of XState and Axios

    Features

    • Provides both XState/Axios by core
    • Returns AxiosInstance and State Machines
    • Reactive, easy to manage states

    Installation

    Using npm:

    npm install query-machine
    

    Using bower:

    bower install query-machine
    

    Using yarn:

    yarn install query-machine
    

    Quick start

    Create a new machine

    // hooks/useQueryMachine.ts
    
    import { useCreateAxiosQueryMachine } from 'query-machine'
    
    export const useQueryMachine = () => {
      const axiosQueryMachine = useCreateAxiosQueryMachine({
        baseURL: 'https://dog.ceo/api'
      })
    
      // axiosQueryMachine
      // [IUseQueryMachine, AxiosInstance]
    
      return axiosQueryMachine
    }

    Use your own AxiosInstance?

    // hooks/useQueryMachine.ts
    
    // You need to install axios
    import axios from "axios"
    import { useCreateQueryMachine } from 'query-machine'
    
    // Create a new axios instance
    // Use this instance to config interceptors, etc...
    export const apiBase = axios.create({ baseURL: 'https://dog.ceo/api' })
    
    export const useQueryMachine = () => {
      const queryMachine = useCreateQueryMachine(apiBase)
    
      return queryMachine
    }

    Example

    import { useQueryMachine } from 'hooks/useQueryMachine'
    
    export const Home = () => {
      const [queryMachine] = useQueryMachine()
      const [dogState, { onGet }] = queryMachine<IDogResponse>()
    
      onGet('/breeds/image/random')
    
      // Check state, context
      // isRequest?
      dogState.matches('request')
      // Context
      dogState.context
      // Data
      dogState.context.data <- Your data here
      return ....
    }

    Checking states

    import { useQueryMachine } from 'hooks/useQueryMachine'
    
    const [queryMachine] = useQueryMachine()
    const [dogState, { onGet }] = queryMachine<IDogResponse>()
    
    // Request to get a random image
    onGet('/breeds/image/random')
    
    
    // isFailure?
    dogState.matches('failure')
    // isIdle?
    dogState.matches('idle')
    // isRequest?
    dogState.matches('request')
    // isSuccess?
    dogState.matches('success')
    Or you can check directly
    import { useQueryMachine } from 'hooks/useQueryMachine'
    
    const [queryMachine] = useQueryMachine()
    const [dogState, { isFailure, isIdle, isRequest, isSuccess }] =
      queryMachine<IDogResponse>()

    Where are errors?

    import { useQueryMachine } from 'hooks/useQueryMachine'
    
    const [queryMachine] = useQueryMachine()
    const [dogState, { onGet, isFailure }] =  queryMachine<IDogResponse>()
    
    // Request to get a random image, but the dog runs away?
    onGet('/breeds/image/random')
    
    // Check status here
    dogState.matches('failure') <- First way to check failure
    isFailure <- Second way to check failure
    
    // Get errors here
    dogState.context.error <- AxiosError

    Interceptors

    // apiBase from hooks
    
    // Add a request interceptor
    apiBase.interceptors.request.use(
      config => {
        // Do something before request is sent
        return config
      },
      error => {
        // Do something with request error
        return Promise.reject(error)
      }
    )
    
    // Add a response interceptor
    apiBase.interceptors.response.use(
      response => {
        // Any status code that lie within the range of 2xx cause this function to trigger
        // Do something with response data
        return response
      },
      error => {
        // Any status codes that falls outside the range of 2xx cause this function to trigger
        // Do something with response error
        return Promise.reject(error)
      }
    )

    Custom request?

    import { useQueryMachine } from 'hooks/useQueryMachine'
    
    const [queryMachine, apiBase] = useQueryMachine()
    const [dogState, { send }] = queryMachine<IDogResponse>()
    
    // Send custom request
    send('REQUEST', {
      request: () => {
        // Do something here?
        const randomDogImage1 = apiBase.get('/breeds/image/random')
        // May do something here again?
    
        return randomDogImage1
      }
    })
    
    // Your data will be here
    dogState.context.data
    Multi requests
    // Your need to install axios
    import axios from 'axios'
    import { useQueryMachine } from 'hooks/useQueryMachine'
    
    const [queryMachine, apiBase] = useQueryMachine()
    const [dogState, { send }] = queryMachine<IDogResponse>()
    
    // Send custom request
    send('REQUEST', {
      request: () => {
        // Do something here?
        const randomDogImage1 = apiBase.get('/breeds/image/random')
        const randomDogImage2 = apiBase.get('/breeds/image/random')
        const randomDogImage3 = apiBase.get('/breeds/image/random')
        // May do something here again?
    
        return axios.all([randomDogImage1, randomDogImage2, randomDogImage3])
      }
    })
    
    // Data will be an array here
    dogState.context.data

    Loader

    import { MachineLoader } from 'query-machine'
    import { useQueryMachine } from 'hooks/useQueryMachine'
    import { useEffectOnce } from 'react-use'
    
    export const Home = () => {
      const [queryMachine] = useQueryMachine()
      const [dogState, { onGet }] = queryMachine<IDogResponse>()
    
      useEffectOnce(() => {
        onGet('/breeds/image/random')
      })
    
      return (
        <MachineLoader
          state={dogState}
          onLoading={() => // Your custom loading component, or you don't need to use this}
          onBuilder={data => {
            const { message } = data
            return <div>{message}</div>
          }}
        />
      )
    }

    Additional information

    // AxiosError
    
    export interface AxiosError<T = any> extends Error {
      config: AxiosRequestConfig;
      code?: string;
      request?: any;
      response?: AxiosResponse<T>;
      isAxiosError: boolean;
      toJSON: () => object;
    }
    // AxiosResponse
    
    {
      "url": "/breeds/image/random",
      "method": "get",
      "headers": {
        "Accept": "application/json, text/plain, */*"
      },
      "baseURL": "https://dog.ceo/api",
      "transformRequest": [null],
      "transformResponse": [null],
      "timeout": 0,
      "xsrfCookieName": "XSRF-TOKEN",
      "xsrfHeaderName": "X-XSRF-TOKEN",
      "maxContentLength": -1,
      "maxBodyLength": -1,
      "transitional": {
        "silentJSONParsing": true,
        "forcedJSONParsing": true,
        "clarifyTimeoutError": false
      }
    }
    // AxiosResponse[]
    
    [
      {
        "data": {
          "message": "https://images.dog.ceo/breeds/pitbull/20190801_154956.jpg",
          "status": "success"
        },
        "status": 200,
        "statusText": "",
        "headers": {
          "cache-control": "no-cache, private",
          "content-type": "application/json"
        },
        "config": {
          "url": "/breeds/image/random",
          "method": "get",
          "headers": {
            "Accept": "application/json, text/plain, */*"
          },
          "baseURL": "https://dog.ceo/api",
          "transformRequest": [null],
          "transformResponse": [null],
          "timeout": 0,
          "xsrfCookieName": "XSRF-TOKEN",
          "xsrfHeaderName": "X-XSRF-TOKEN",
          "maxContentLength": -1,
          "maxBodyLength": -1,
          "transitional": {
            "silentJSONParsing": true,
            "forcedJSONParsing": true,
            "clarifyTimeoutError": false
          }
        },
        "request": {}
      },
      {
        "data": {
          "message": "https://images.dog.ceo/breeds/retriever-golden/Z6A_4500_200808.jpg",
          "status": "success"
        },
        "status": 200,
        "statusText": "",
        "headers": {
          "cache-control": "no-cache, private",
          "content-type": "application/json"
        },
        "config": {
          "url": "/breeds/image/random",
          "method": "get",
          "headers": {
            "Accept": "application/json, text/plain, */*"
          },
          "baseURL": "https://dog.ceo/api",
          "transformRequest": [null],
          "transformResponse": [null],
          "timeout": 0,
          "xsrfCookieName": "XSRF-TOKEN",
          "xsrfHeaderName": "X-XSRF-TOKEN",
          "maxContentLength": -1,
          "maxBodyLength": -1,
          "transitional": {
            "silentJSONParsing": true,
            "forcedJSONParsing": true,
            "clarifyTimeoutError": false
          }
        },
        "request": {}
      }
    ]

    Credits

    A special thanks to XState and Axios

    License

    MIT

    Install

    npm i query-machine

    DownloadsWeekly Downloads

    93

    Version

    1.5.1

    License

    MIT

    Unpacked Size

    32.4 kB

    Total Files

    37

    Last publish

    Collaborators

    • andyng