# useResourceBasic hook for sending REST API from within React Component.
Copy useResource ( config : ResourceConfig )
Copy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'users' ,
endpoint : '/users' ,
}
function MyReactComponent ( ) {
const {
data ,
isLoading ,
options ,
errors ,
filters ,
fetch ,
fetchOptions ,
create ,
replace ,
update ,
remove ,
setData ,
setLoading ,
setErrors ,
setFilters ,
clear ,
} = useResource ( resourceConfig )
}
# namespaceresource
module uses Redux global state managment. When you call some action for the first time it will create new item in Redux store with key that is equal to namespace
.
Please pay attantion that namespace
should be some unique miningfull variable. In case you will use same namespace
for all your configurations it will just override each other
When you first open application Redux store is empty
first component to render
Copy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'myAppData' ,
}
function APP ( ) {
const { filters , setData } = useResource ( resourceConfig )
useEffect ( ( ) => setData ( { test : 'data' } ) , [ ] )
return < User />
}
redux store
Copy {
myAppData : {
test : 'data'
}
}
second compoent to Render
Copy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'user' ,
}
function User ( ) {
const { filters , setData , setLoading , setErrors , setFilters } = useResource ( resourceConfig )
useEffect ( ( ) => {
setData ( { name : 'Alex' } )
setLoading ( true )
setErrors ( 'no errors' )
setFilters ( { some : 'filters' } )
} , [ ] )
}
redux store
Copy {
myAppData : {
data : {
test : 'data'
}
} ,
user : {
data : {
name : 'Alex'
} ,
isLoading : true ,
errors : 'no errors' ,
filters : {
some : 'filters'
}
}
}
second compoent add clear data
Copy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'user' ,
}
function User ( ) {
const { filters , setData , setLoading , setErrors , setFilters , clear } = useResource ( resourceConfig )
useEffect ( ( ) => {
setData ( { name : 'Alex' } )
setLoading ( true )
setErrors ( 'no errors' )
setFilters ( { some : 'filters' } )
return clear
} , [ ] )
}
redux store
Copy {
myAppData : {
data : {
test : 'data'
}
}
}
You can use short Synax of Resource config
Copy useResource ( { namespace : 'user' } )
is same as
# endpointResource configuration to setup API URL so send HHTP requests
# Static urlCopy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'users' ,
endpoint : 'users'
}
function APP ( ) {
const { fetch , create } = useResource ( resourceConfig )
useCallback ( ( ) => fetch ( ) )
useCallback ( ( ) => create ( ) )
}
You can use short Synax of Resource config
Copy
const resourceConfig = {
namespace : 'users' ,
endpoint : 'users'
}
useResource ( resourceConfig )
is same as
# Dynamic urlCopy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'users' ,
endpoint : 'users/:deparment/:office?'
}
function APP ( ) {
const { fetch } = useResource ( resourceConfig )
useCallback ( ( ) => fetch ( { deparment : 'developers' } ) )
useCallback ( ( ) => fetch ( { deparment : 'developers' , office : 'UK' } ) )
}
You can use short Synax of Resource config
Copy
const resourceConfig = {
namespace : 'users' ,
endpoint : 'users/:deparment/:office?'
}
useResource ( resourceConfig )
is same as
Copy useResource ( 'users/:deparment/:office?' )
# baseURLBy default resource module will automatically appent /api/
prefix to all endpoints
Copy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'users' ,
endpoint : 'users'
}
function APP ( ) {
const { fetch , create } = useResource ( resourceConfig )
useCallback ( ( ) => fetch ( ) )
}
To change this behavior use baseURL
config
Copy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'users' ,
endpoint : 'users' ,
baseURL : '/'
}
function APP ( ) {
const { fetch , create } = useResource ( resourceConfig )
useCallback ( ( ) => fetch ( ) )
}
# queriesqueries
is an Array of all posible query params that aceepts current endpoint
All other params that is not described in queries
resourceConfig will be omited from queryString
After each API call resource
module will store query params from the latest API call in filters
object
Copy import { useResource } from '@cranium/resource'
const resourceConfig = {
namespace : 'globalData' ,
endpoint : 'context' ,
queries : [ 'accountId' , 'keys' ]
}
function MyReactComponent ( ) {
const { fetch , create , filters } = useResource ( resourceConfig )
useCallback ( ( ) => fetch ( ) )
useCallback ( ( ) => fetch ( { accountId : 14 } ) )
useCallback ( ( ) => fetch ( { accountId : 14 , keys : 'PERMISSIONS' } ) )
useCallback ( ( ) => fetch ( { accountId : 14 , keys : [ 'PERMISSIONS' , 'ROLES' ] } ) )
useCallback ( ( ) => create ( { missed : 'test' , price : 0 } ) )
return {
< >
< p > Filters from latest requests </ p >
< p > { JSON . stringify ( filters ) } </ p >
</ >
}
}
# cacheCache module configuration to store API data in storage.
For more info, use the link
# transformValueFunction to modify API responce data before passing to React component and caching.
Copy import { useResource } from '@cranium/resource' ;
const resourceConfig = {
namespace : 'profile' ,
endpoint : 'users/me' ,
transformValue : ( userData ) => ( { ... userData , fullName : ` ${ userData . fistName } ${ userData . lastName } ` } )
}
function MyComponent ( ) {
const { data } = useResource ( resourceConfig )
}
# transformErrorsFunction to modify API responce errors before passing to React component
Copy import { useResource } from '@cranium/resource' ;
const resourceConfig = {
namespace : 'profile' ,
endpoint : 'users/me' ,
transformErrors : ( erros ) => ( { error : erros . message } )
}
function MyComponent ( ) {
const { data } = useResource ( resourceConfig )
}
# forceUpdatesDefault work flow for async actions like (fetch, create, delete, update...) is:
Call async action from react Component Set isLoading
true, save url and query params to filters
Send HTTP request Save data/errors on respoce, Set isLoading
false You can omit changing isLoading
, errors
and filters
data by setting forceUpdates
to true
, so that only data
will be changing.
Most common case for this configuration is when you use some react npm packages to work with form. In most cases that libraries provides it own handles for submitting and errors so that you can use this config for better performance and to avoid dublicated indicators
# reducerFunction that will be called in redux reducer . Default 'replace'
.
By default connect resources has already defined 4 types of most reusable reducers.
And you may use it as a String.
Or you can create your own reducer and pass is as a function
Copy useResource ( { namespace : 'cars' , reducer : 'object' } )
useResource ( { namespace : 'cars' , reducer : 'none' } )
useResource ( { namespace : 'cars' , reducer : 'replace' } )
useResource ( { namespace : 'cars' , reducer : 'infinityList' } )
useResource ( { namespace : 'cars' , reducer : myCustomReducer } )
# object
reducerMerge prev state and action payload
Copy function objectReducer ( state , action ) {
return { ... state , ... action . payload }
}
# none
reducerDo not change store data
Copy function noneReducer ( state , action ) {
return state
}
# replace
reducerSkip store data and use action payload
Copy function replaceReducer ( state , action ) {
return action . payload
}
# infinityList
reducerThis is the most complex type of reducers that works for endpoint with list data types
Copy {
"count" : 10 ,
"results" : [ ]
}
infinityList
helpful when you work with infinity List to load next items on scroll to bottom. The basic idea of infinity lists is that when u first enter the page you need to send GET request for first n
rows and on scroll end send one more request to get next batch of data and join 2 array. Next problem is inline editing.
Copy function infinityListReducer ( state , action ) {
return {
... state ,
... action . payload ,
results : [ ... state . results , ... action . payload . results ]
}
}
# custom reducer functionYou may create your own logic for reducer. For example:
Copy function myCustomReducer ( state , payload ) {
return { ... state , ... payload , count : state . count + 1 }
}
useResource ( { namespace : 'cars' , reducer : myCustomReducer } )