useCroods
This hook receives a configuration object that can override every prop described on CroodsProvider as well as the options below.
| Property | Type | Required | Default |
|---|---|---|---|
| name | String | ✔ | - |
| path | String | - | |
| customPath | String | - | |
| stateId | String | - | |
| operation | 'info' or 'list' | - | |
| query | Object | - | |
| id | String | - | |
| fetchOnMount | Bool | ✔ | false |
name
String: This options is required everytime you use Croods, be it on a useCroods hook or Fetch component.
If you don't use the path param, Croods will build your endpoint request based on the name/ id options.
This options also controls the key name of your state in the Global State object.
Usage:
For instance, if you use name: 'todos' it will change your request and your global state as follows:
const MyComponent = () => {
const tuple = useCroods({ name: 'todos', fetchOnMount: true })
// GET /todos
// state = { todos: { list: [...], fetchingList: false, ... } }
}
Then, if you use the same name in other component, you'll have access to the same state under todos key.
const OtherComponent = () => {
const [{ list }, { save }] = useCroods({ name: 'todos' })
// list will already be populated, without having to fetch again
console.log(list) // [{ text: 'Foo', completed: true }]
}
If your other component also fetches the same endpoint, it'll avoid the extra request if you set cache to true.
path
String: Use this option when you want to set an endpoint that is different than the name.
Croods will still append your given id at the end of your path
Usage:
// with id
const tuple = useCroods({
name: 'todos',
id: 1,
path:"/foo/bar",
fetchOnMount: true
})
// GET /foo/bar/1
// without id
const tuple = useCroods({
name: 'todos',
path:"/foo/bar",
fetchOnMount: true
})
// GET /foo/bar
customPath
String: Use this option when you want to prevent Croods from managing your endpoint.
It will override the request endpoint with the one you provide. This also affects the behavior of the id option. It takes precedence over path (which means, path will not be used).
Usage:
const [_, { save }] = useCroods({
name: 'todos',
id: 1, // this is not going to be used
path: "bar/foo", // this is not going to be used
})
save({ customPath: '/foo/bar/' })()
// POST /foo/bar
You can explicitly tell Croods where to insert your id:
const [, { save }] = useCroods({
name: 'todos',
id: 1, // this is going to be used
path: "bar/foo", // this is not going to be used
})
save({ customPath: '/foo/:id/bar/' })()
// POST /foo/1/bar
operation
String: It can be either 'info' or 'list'. This is used to change the default behavior or the fetch action so it does not matter if you passed an id or not, the parsed result of the response will end up in the given piece of the state.
When the API is responding differently to what Croods expects - that means responding with an object when GET List requests or the opposite - and you want to have that object set in the info instead of list state, then you should use this prop. It works the other way around, when a GET Info will reply with a list that you want set in the list state.
This prop will actually change the Actions from List Request/Success/Failure to Info Request/Success/Failure or from Info Request/Success/Failure to List Request/Success/Failure.
Usage:
// Normal behavior
const [{ list }] = useCroods({ name: 'todos' })
const [{ info }] = useCroods({ name: 'colors', id: 1 })
// Expected behavior
const [{ info }] = useCroods({ name: 'todos', operation: 'info' })
const [{ list }] = useCroods({ name: 'colors', id: 1, operation: 'list' })
Important: It only works on fetch operations so it should actually be used with the action like so:
const [{ info }, { fetch }] = useCroods({ name: 'todos' })
React.useEffect(() => {
fetch({ operation: 'info' })()
}, [])
query
Object: This is used on GET requests, when you want to send query parameters (parameters on your URL) when fetching is called by Croods (read fetchOnMount).
It will convert a given object with numbers, strings and array values to a queryString format.
Usage:
const tuple = useCroods({
name: 'todos',
query: { page: 2, tags: ['red', 'yellow'] },
fetchOnMount: true,
})
// GET /todos?page=2&tags[]=red&tags[]=yellow
id
String|Number: For requests aiming a single item, like GET info, PUT or DELETE. You can pass this option so croods will guess the endpoint.
It will do it by joining name with the given id as follows:
Usage:
const tuple = useCroods({
name: 'todos',
id: 1,
fetchOnMount: true,
})
// GET /todos/1
// state = { todos: { info: {...}, fetchingInfo: true, ... } }
Important: If you use customPath this id will not be appended to the endpoint.
stateId
String: This prop is optional and will store your data state in a separate piece of the Global state.
It is usefull for when you want to make requests in an already used endpoint but you don't want to mess with the data you already have stored.
For instance, you want to grab the list of todos from a single user but you want to keep the list of all todos in your homepage untouched, or you want to grab a list of todos under a certain tag:
const [{ list }, { fetch }] = useCroods({ name: 'todos', stateId: 'completed' })
fetch()({ tags: ['completed'] })
The code above will not interfere on your todos, because your global state will look like this:
{
'todos': { list: [/* 10 items */], ... },
'todos@completed': { list: [/* 3 items */], ... },
}
Thus if you are caching and go back to the homepage you will still have your untouched list with 10 items without having to fetch again.
Usage:
const tuple = useCroods({
name: 'todos',
stateId: 'user',
fetchOnMount: true,
})
// GET /todos
// state = { todos@user: { list: [...], fetchingList: false, ... } }
fetchOnMount
Boolean: set it to true if you want the useCroods hook to fetch (send a GET request) as soon as the component mounts.
We recommend using the Fetch component when you want to fetch something and useCroods hook when you want to perform the other actions.
But you may have a good reason to use it this way. One of the main reasons we aknowledge is avoiding the nesting hell that the render props approach give you.
For instance, this code:
const Form = ({ id }) => {
const [{ info: todos }] = useCroods({ name: 'todos', fetchOnMount: true })
const [{ info: colors }] = useCroods({ name: 'todos', fetchOnMount: true })
const [, { save }] = useCroods({ name: 'submissions' })
return (
<form onSubmit={save()}>
<label>Select a task</label>
<select>{todos.map(todo => <option>{todo.title}</option>)}</select>
<label>Select a color</label>
<select>{todos.map(todo => <option>{todo.title}</option>)}</select>
<button>Submit</button>
</form>
)
}
reads much better then this one:
const Form = () => {
const [, { save }] = useCroods({ name: 'submissions' })
return (
<Fetch
name="todos"
render={todos => (
<Fetch
name="colors"
render={colors => (
<form onSubmit={save()}>
<label>Select a task</label>
<select>{todos.map(todo => (
<option>{todo.title}</option>
))}</select>
<label>Select a color</label>
<select>{todos.map(todo => (
<option>{todo.title}</option>
))}</select>
<button>Submit</button>
</form>
)}
/>
)}
/>
)
}
or 😅:
const Todos = () => (
<Fetch
name="todos"
render={todos => <Colors todos={todos} />}
/>
)
const Colors = ({ todos }) => (
<Fetch
name="colors"
render={colors => <Form todos={todos} colors={colors} />}
/>
)
const Form = ({ todos, colors }) => {
const [, { save }] = useCroods({ name: 'submissions' })
return (
<form onSubmit={save()}>
<label>Select a task</label>
<select>{todos.map(todo => (
<option>{todo.title}</option>
))}</select>
<label>Select a color</label>
<select>{todos.map(todo => (
<option>{todo.title}</option>
))}</select>
<button>Submit</button>
</form>
)
}
Don't forget the loading / errors / empty states
There's a good reason to have the Fetch component though, read more about it here.