CroodsProvider
Important: The purpose of this component is to set defaults to your project.
Every one of the props below can be overriden by the usage of <Fetch />
, useCroods
or any Croods action.
The table bellow presents all the props you can pass to the Provider. Further down the page there are detailed descriptions of each.
(Click on any name to navigate directly to its information.)
Property | Type | Required | Default |
---|---|---|---|
baseUrl | String | ✔ | - |
credentials | object | - | |
cache | Bool | false | |
debugActions | Bool | false | |
debugRequests | Bool | false | |
headers | Func/object | - | |
handleResponseHeaders | Func | - | |
afterResponse | Func | - | |
afterSuccess | Func | - | |
afterFailure | Func | - | |
after4xx | Func | - | |
after5xx | Func | - | |
paramsParser | Func | snakeCase | |
paramsUnparser | Func | camelCase | |
parseResponse | Func | response => response.data | |
parseFetchResponse | Func | - | |
parseListResponse | Func | - | |
parseInfoResponse | Func | - | |
parseSaveResponse | Func | - | |
parseCreateResponse | Func | - | |
parseUpdateResponse | Func | - | |
parseErrors | Func | - | |
queryStringParser | Func | - | |
renderError | Func | - | |
renderEmpty | Func | - | |
renderLoading | Func | - | |
requestTimeout | number | 0 (no timeout) | |
urlParser | Func | kebabCase |
baseUrl
String: It defines the api url which all other paths used in croods components will be relative too.
<CroodsProvider
baseUrl="https://dog.ceo/api/breed/beagle"
>
<Fetch
name="images"
render={...}
/>
</CroodsProvider>
The code above will send a GET
request to https://dog.ceo/api/breed/beagle/images
.
credentials
Object: If you want to send credentials on your requests, just pass an object here with the following format:
const credentials = {
username: 'janedoe',
password: 's00pers3cret',
}
This is gonna send the auth
property from axios.
cache
Boolean: Pass true
if you want to cache your requests, which means that if you unmount and mount again a component that fetches data through Croods and you already have equivalent data on info
or list
, it will use the old data and avoid a request.
<Fetch
name="auth"
cache
render={currentUser => currentUser.name}
/>
Use it wisely, caching is source of weird bugs and awesome speed ;).
We recommend not setting it as default for your whole app, but to be used by components (on Fetch
and useCroods
).
debugActions
Boolean: It logs all the Croods Actions to your JS Console. We recommend using it on development environment.
Check out the debugging section if you want to read more about it.
<CroodsProvider baseUrl="https://dog.ceo/api/breed/beagle" debugActions>
<MyApp />
</CroodsProvider>
debugRequests
Boolean: It logs all the API requests to your JS Console. We recommend using it on development environment.
Check out the debugging section if you want to read more about it.
<CroodsProvider baseUrl="https://dog.ceo/api/breed/beagle" debugRequests>
<MyApp />
</CroodsProvider>
headers
Object|Function: use this prop to send headers along with your requests.
Croods already has some default headers that will be merged/overriden by the ones you provide here. These are our defaults:
{ 'Accept': 'application/json', 'Content-Type': 'application/json' }
You can send new headers as an object:
<CroodsProvider headers={{ 'Access-Token': 08f90ds8f90sd }} />
// { 'Accept': 'application/json', 'Content-Type': 'application/json', 'Access-Token': 08f90ds8f90sd }
Or you can send a function, even a Promise that should return an object:
const getHeaders = async () => {
const stored = await AsyncStorage.getItem('authCredentials')
const headers = JSON.parse(stored)
return {
'Access-Token': headers.accessToken,
'Token-Type': headers.tokenType,
}
}
<CroodsProvider headers={getHeaders} />
handleResponseHeaders
Format: object => void
Function: This function is a callback dispatched right before every afterSuccess or afterFailure, and will receive the response. It is intented to be used for saving the response.headers
in case your API changes the tokens on every request.
const saveHeaders = headers => {
const string = JSON.stringify(headers)
AsyncStorage.setItem('authCredentials', string)
}
<CroodsProvider handleResponseHeaders={response => saveHeaders(response.headers)} />
afterResponse
Format: object => void
Function: This function is a callback dispatched right after every API response, before even our state has changed. It'll receive the full response object (with headers, data...) or the error.response
if it exists when the request fails. It won't be called if the Error does not have a response.
It is the place to add your side effects, like redirecting, analytics, showing notifications, etc.
const [, { save }] = useCroods({
name: 'colors',
afterResponse: response => response.status < 400
? alert('Data was saved')
: alert('Data could not be saved')
})
afterSuccess
Format: object => void
Function: This function is a callback dispatched right after every successfull API request, right before afterResponse. It'll receive the full response object (with headers, data...) and should not return anything.
It is the place to add your side effects, like redirecting, analytics, showing notifications, etc.
const [, { save }] = useCroods({
name: 'auth',
path: 'auth/sign_in',
afterSuccess: () => navigate('/')
})
afterFailure
Format: Error => void
Function: This function is a callback dispatched right after every failed API request, right before afterResponse. It'll receive the Error
and should not return anything.
It is the place to add your side effects, like redirecting, analytics, showing notifications, etc.
Redirecting users that fail to authenticate:
const [{ info: currentUser }] = useCroods({
name: 'auth',
path: 'auth/validate_token',
fetchOnMount: true
afterFailure: () => navigate('/sign-in')
})
after4xx
):
Redirecting users when API returns 404 (see <Fetch
name="todos"
afterFailure={error => {
if (error.response.status === 404) {
navigate('/not-found')
}
}}
/>
after4xx
Format: (number, string?, object?) => void
Function: This function is a callback dispatched right after every failed API request with status 4XX (400, 404, etc), right before afterFailure. It'll receive the status code, status message and the error data.
It is a convenience function to add your side effects, like redirecting, analytics, showing notifications, etc.
Redirecting users that fail to authenticate:
const [{ info: currentUser }] = useCroods({
name: 'auth',
path: 'auth/validate_token',
fetchOnMount: true,
after4xx: (code, message, data) => {
if (code === 403) {
navigate('/sign-in')
} else {
alert(`${code} - ${message}`)
console.log(data)
}
},
})
Redirecting users when API returns 404:
<Fetch
name="todos"
after4xx={code => code === 404 && navigate('/not-found')}
/>
after5xx
Format: (number, string?, object?) => void
Function: This function is a callback dispatched right after every failed API request with status 5XX (500, 503, etc), right before afterFailure. It'll receive the status code, status message and the error data.
It is a convenience function to add your side effects, like redirecting, analytics, showing notifications, etc.
Redirecting users when service is unavailable:
<Fetch
name="todos"
after5xx={(code, message, data) => {
if (code === 503) {
navigate('/service-unavailable')
} else {
alert(`${code} - ${message}`)
console.log(data)
}
}}
/>
paramsParser
Format: string => string
Function: This function converts the case of our data object's keys before sending them to the backend.
We assume that in our app we want to have all object's keys using camelCase
. This is the JS standard. For instance, this is how we use to describe an object:
const person = { fullName: 'John Doe', homeAddress: '100 5th Ave' }
Most APIs, specially the ones not written in JS, expect a different standard though. For instance, the Rails APIs expect snake_case
.
Given that we work mostly with Rails APIs, we left the default to snake_case which means that someKey
will become some_key
. For instance:
const [, { save }] = useCroods({ name: 'colors' });
<button onClick={() => save()({ color: 'red', pantoneValue: '19-1664' })}>
Create a red color
</button>
// When clicked, we will send a `POST /colors` with this data:
{ "color": "red", "pantone_value": "19-1664" }
Fell free to change it, depending on your API standards, by changing this prop at <CroodsProvider>
.
paramsUnparser
Format: string => string
Function: This function is used along with paramsParser to convert the data back from the server to our frontend standard.
Given that JS standard is camelCase
we left it as default, which means that some_key
will become someKey
. For instance, our API would send the data in this format:
{ "id": "1", "color": "red", "pantone_value": "19-1664" }
And we'll have it available as:
const [{ info }] = useCroods({ name: 'colors', fetchOnMount: true })
console.log(info.pantoneValue) // `19-1664`
Fell free to change it, depending on your API standards, by changing this prop at <CroodsProvider>
.
parseResponse
Format: object => object
Default: response => response.data
Function: Extracts your info
and list
from the API's responses.
It will be overriden by any of the parse response methods described below.
When a successfull response comes from the server, this function will receive the whole object response with the following format:
{
headers: { ... },
data: {
// Your API response here
},
}
Then you should instruct Croods how to get the data you want on your state.info
and state.list
from that object.
Let's say your server uses this format:
{
"status": "success",
"message": [
"https://images.dog.ceo/breeds/beagle/n02088364_10108.jpg",
"https://images.dog.ceo/breeds/beagle/n02088364_10206.jpg"
]
}
Then we know our response
object looks like this:
{
headers: { ... },
data: {
status: 'success',
message: [
'https://images.dog.ceo/breeds/beagle/n02088364_10108.jpg',
'https://images.dog.ceo/breeds/beagle/n02088364_10206.jpg',
],
},
}
So our parseResponse
should be:
<CroodsProvider
parseResponse={response => response.data.message}
render={...}
>
If your API has different patterns for different request methods, use the more specific parse response methods described below.
If you are in doubt about your server responses, read more about debugRequests
.
parseFetchResponse
Format: object => object
Default: parseResponse
Function: Extracts your info
and list
from the API's GET
responses.
It has higher priority over parseResponse
and can be overriden by parseListResponse
and parseInfoResponse
.
Read more about parseResponse to understand what it does.
parseListResponse
Format: object => object
Default: parseResponse
Function: Extracts your list
from the API's GET
response.
It has higher priority over parseFetchResponse
and parseResponse
.
Read more about parseResponse to understand what it does.
parseInfoResponse
Format: object => object
Default: parseResponse
Function: Extracts your info
from the API's GET
response.
It has higher priority over parseFetchResponse
and parseResponse
.
Read more about parseResponse to understand what it does.
parseSaveResponse
Format: object => object
Default: parseResponse
Function: Extracts your info
from the API's POST/PUT
responses.
It has higher priority over parseResponse
and can be overriden by parseCreateResponse
and parseUpdateResponse
.
Read more about parseResponse to understand what it does.
parseCreateResponse
Format: object => object
Default: parseResponse
Function: Extracts your info
from the API's POST
response.
It has higher priority over parseSaveResponse
and parseResponse
.
Read more about parseResponse to understand what it does.
parseUpdateResponse
Format: object => object
Default: parseResponse
Function: Extracts your info
from the API's PUT
response.
It has higher priority over parseSaveResponse
and parseResponse
.
Read more about parseResponse to understand what it does.
parseErrors
Format: (Error, string) => string
Function: Extracts an error message from any Error
on either Croods actions. This string will be stored in the respective action error state (eg: saveError
, infoError
, listError
, destroyError
).
It will replace Croods own defaultParseError
. Also, the message generated by the default parser is provided as a second argument to your function, to avoid extra work if you only want to parse specific errors, for example.
<Fetch
name="todos"
parseErrors={(error, defaultMessage) => {
if (error.response
&& error.response.statusMessage === "Some specific Error") {
return `Some specific message`
}
return defaultMessage
}}
renderError={error => (
<span style={{ color: 'red' }}>
{error}
</span>
)}
render={...}
/>
In the example above, our renderError
will render the string returned from our custom parseErrors
.
queryStringParser
Format: string => string
Function: This function converts the case of our queryString object's keys for composing the endpoint url.
The main purpose of this config is to be able to use short hand property names when composing the query string:
// Normal behavior
<Fetch name="users" query={{ page: 2, shouldCache: true }} render={...} />
// GET /users?page=2&shouldCache=true
// Using this config
<Fetch name="users" queryStringParser={kebabCase} query={{ userRole }} render={...} />
// GET /users?user-role=admin
renderError
Format: string => React element
Function: Sets a default renderError
for all of your Fetch
components.
Read more about it here.
renderEmpty
Format: () => React element
Function: Sets a default renderEmpty
for all of your Fetch
components.
Read more about it here.
renderLoading
Format: () => React element
Function: Set a default renderLoading
for all of your Fetch
components.
Read more about it here.
requestTimeout
Number: If you want your requests to time out, just pass the amount of milliseconds in this prop.
The default is 0 (no timeout) which means the requests will never timeout.
For instance, let's say we want some request to timeout if it doesn't resolve in under 3 seconds:
<Fetch name="todos" timeout={3000} render={...} />
urlParser
Format: string => string
Function: If you don't use the path
or customPath
params, Croods builds your endpoints based on name
and id
.
It means that Croods will join the given name
with the id
(for GET info
, PUT
and DELETE
requests) or just the name
(for GET list
and POST
requests).
This function is usefull to transform the name
into a valid endpoint for your API.
The default parser is kebab-case which means that thisName
will become this-name
. For instance:
<Fetch name="userPosts" render={...} />
// GET /user-posts
<Fetch name="userPosts" id={1} render={...} />
// GET /user-posts/1
You can pass a custom function here to customize this behavior. Let's say our API endpoints follow the snake_case
pattern:
import snakeCase from 'lodash/snakeCase'
<CroodsProvider urlParser={snakeCase}>
<Fetch name="userPosts" render={...} />
</CroodsProvider>
// GET /user_posts