@ltipton/useapi
TypeScript icon, indicating that this package has built-in type declarations

0.2.1 • Public • Published

Build Client API

  • Generates hooks to make API calls based on a passed in Api Options
  • Allows defining a simple model for a group of endpoints to generate the hooks

Api Options

  • The Options are split into two parts queries and mutations
  • With each, a route-model should be defined for each individual endpoint

Query Endpoints

  • All query endpoints should be defined under queries property
  • All endpoints defined within the queries property will make a get request
    • The get request is hard coded, and currently can not be changed

Mutation Endpoints

  • All mutation endpoints should be defined under mutations property
  • Mutation endpoints can make request of the following types
    • post, patch, put, delete
  • Other than the delete methods, each mutation hook accepts a payload object
    • The payload object should include the body content of the request

Route model

  • Both queries and mutations are defined by a route-model
  • A route-model is defined by the following properties
    • method - The HTTP verb to use when making the request
    • route - The request url path name, i.e. /strategies/23/pillars
      • Can be a string or function
      • As a function, it will be called with the Hook Options passed to the calling hook
    • payload - Used as the body of the request for mutations only
    • onError - Callback called when an error is thrown durning the request
    • onSuccess - Callback called when a request is successful
    • onBefore - Callback called before a request is made
      • Useful for validating the payload of a mutation
      • If this callback throws an error, it will be caught
      • All caught errors will skip the request and be passed to the onError callback as a NetworkError
      • If this callback returns false, a generic error will be throw
      • The callback should return anything other than false to not throw an error
    • onUnMount - Callback called when a get request is made and the calling Component unmounts
      • Useful for cleaning up local state when desired

Api Options Example

const endpointHooks = buildApiClient({
  queries: {
    getAll: {
      // Will use 'get' regardless of what is defined here
      method: `get`,
      route: `/api/endpoint/pathname`,
      // Called when the parent component is unmounted
      onUnMount: () => {},
      // Called when a error is thrown durning a request
      // This includes errors in the `onBefore` callback
      onError: (error: any) => {},
      // Called when a request is successful
      onSuccess: <T>(result: T) => {},
    },
    get: {
      method: `get`,
      // The route as a function
      route: (data: HookMethodOptions) => `/endpoint/${data.payload.id}`,
      // Callback methods are not required
    },
  },
  mutations: {
    create: {
      // Can be any mutation HTTP verb - post, put, patch, delete
      method: 'post',
      // Accepts all the same arguments as queries
      // The `onUnMount` callback is ignored for all mutations
    },
  },
})

Api Client Hooks

  • The buildApiClient method returns an object with properties matching the passed in Api Options object
  • It is split into two parts queries and mutations same as the Api Options object
  • Within both the queries and mutations properties are React Hook functions
    • These are real hooks and follow all the same rules as normal react hooks
    • They must be called within the body of a Function Component
    • They can NOT be called conditionally
  • These hooks use closures
    • This allows them to maintain access to the Api Options object originally passed when they were being built
    • This allows defining properties and logic for an API request in a single location, and then reusing it where needed
  • It is recommended to export the hooks built from the buildApiClient method using the use prefix
    • This is the same pattern used by react, let others know it is a hook, and not regular function
    • For example:
      • If I have a hook called getItem
      • I would export it as useItem

Hooks Example

  • Given the same endpointHooks as defined in the above example
  • The buildApiClient method would return the following object
const endpointHooks = {
  queries: {
    // Contains references to the queries.get route-model above
    get: useQuery,
    // Contains references to the queries.getAll route-model above
    getAll: useQuery,
  }
  mutations: {
    // Contains references to the mutations.create route-model above
    create: useMutation,
  }
}

Query Hooks

  • The useQuery hook is built internally when the buildApiClient method is called
  • All route-model defined in the queries property of the Api Options will be converted into a useQuery hook
  • These hooks can be access from the queries property of the response of the buildApiClient method call
    • For example:
      • Given I pass the following Api Options object => { queries: { get: { ...<route-model> }}}
      • I can access the hook for the get hook in the response from buildApiClient at response.queries.get
  • Unlike the mutation hooks, the request made by the useQuery hook are initiated immediately

Query Hook Options

  • This hook accepts an options object with the similar properties as in the initial Api Options object route-model
  • Properties in this object will impact original route-model properties in the following ways
    • payload => Is merged with the original payload
    • onBefore | onSuccess | onError | onUnMount => Will overwrite the original method
      • These methods can be defined inline without the need for memoization
      • The onUnMount callback exists for mutations only
    • route => When route is a function, the options object will be passed as the first argument
  • Aside from the above properties, the options object has the following
    • enabled - If false, the API call will be by-passed
    • cache - If true, the response will be cached. Future calls will use the cached response until cleared
      • Cache exists for queries only
    • apiOptions - Object passed on to the axios client
      • mapper? - (item: Record<string, any>[]) => any[]
      • config? - AxiosRequestConfig from the axios library

Query Hook Response

  • The hook response contains the following properties
    • loading - Is true when the API request is in flight
    • data - The API client response. Is undefined until a successful API call is made
    • error - Network Error response. Is undefined until an error is thrown, or the API call fails
    • clearCache - Clears the cache for the specific API call
    • getCache - Returns the cached response for the specific API call

Mutation Hooks

  • The useMutation hook is built internally when the buildApiClient method is called
  • All route-model defined in the mutations property of the Api Options will be converted into a useMutation hook
  • These hooks can be access from the mutations property of the response of the buildApiClient method call
    • For example:
      • Given I pass the following Api Options object => { mutations: { post: { ...<route-model> }}}
      • I can access the hook for the post hook in the response from buildApiClient at response.mutations.post
  • Unlike the query hooks, the request made by the mutation hook are NOT immediately initiated
    • Instead they return a useMutation hook that must be called to initiate the API call

Mutation Hook Options

  • This hook accepts an options object with the similar properties as in the initial Api Options object route-model
  • Properties in this object will impact original route-model properties in the following ways
    • payload => Is merged with the original payload
    • onBefore | onSuccess | onError | onUnMount => Will overwrite the original method
      • These methods can be defined inline without the need for memoization
      • The onUnMount callback exists for mutations only
    • route => When route is a function, the options object will be passed as the first argument
  • Aside from the above properties, the options object has the following
    • enabled - If false, the API call will be by-passed
    • apiOptions - Object passed on to the axios client
      • mapper? - (item: Record<string, any>[]) => any[]
      • config? - AxiosRequestConfig from the axios library

Mutation Hook Response

  • The hook response contains the following properties
    • loading - Is true when the API request is in flight
    • data - The API client response. Is undefined until a successful API call is made
    • error - Network Error response. Is undefined until an error is thrown, or the API call fails
    • useMutate - Hook that will make the actual API request
      • Mutation hooks are not called immediately in the way that query hooks are
      • Instead this useMutation hook is returned and that must be called to initiate the API call

Readme

Keywords

none

Package Sidebar

Install

npm i @ltipton/useapi

Weekly Downloads

2

Version

0.2.1

License

MIT

Unpacked Size

129 kB

Total Files

33

Last publish

Collaborators

  • lktipton