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
andmutations
- 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 aget
request- The
get
request is hard coded, and currently can not be changed
- The
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 apayload
object- The
payload
object should include the body content of the request
- The
Route model
- Both
queries
andmutations
are defined by aroute-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 formutations
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 aNetworkError
- 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 aget
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 inApi Options
object - It is split into two parts
queries
andmutations
same as theApi Options
object - Within both the
queries
andmutations
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
- This allows them to maintain access to the
- It is recommended to export the hooks built from the
buildApiClient
method using theuse
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
- If I have a hook called
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 thebuildApiClient
method is called - All
route-model
defined in thequeries
property of theApi Options
will be converted into auseQuery
hook - These hooks can be access from the
queries
property of the response of thebuildApiClient
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 frombuildApiClient
atresponse.queries.get
- Given I pass the following
- For example:
- Unlike the
mutation
hooks, the request made by theuseQuery
hook are initiated immediately
Query Hook Options
- This hook accepts an
options
object with the similar properties as in the initialApi Options
objectroute-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
-
mapper? -
-
enabled - If
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
-
loading - Is
Mutation Hooks
- The
useMutation
hook is built internally when thebuildApiClient
method is called - All
route-model
defined in themutations
property of theApi Options
will be converted into auseMutation
hook - These hooks can be access from the
mutations
property of the response of thebuildApiClient
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 frombuildApiClient
atresponse.mutations.post
- Given I pass the following
- For example:
- Unlike the
query
hooks, the request made by themutation
hook are NOT immediately initiated- Instead they return a
useMutation
hook that must be called to initiate the API call
- Instead they return a
Mutation Hook Options
- This hook accepts an
options
object with the similar properties as in the initialApi Options
objectroute-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
-
mapper? -
-
enabled - If
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
-
loading - Is