# 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 } )