Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to refetch a query in useQuery and useQueryWithStore #6130

Merged
merged 8 commits into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/Actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ The return value of `useQuery` is an object representing the query state, using
- `error`: `null` unless the `dataProvider` threw an error, in which case it contains that error.
- `loading`: A boolean updating according to the request state
- `loaded`: A boolean updating according to the request state
- `refetch`: A function you can call to trigger a refetch. It's different than the `refresh` function returned by `useRefresh` as it won't trigger a refresh of the view, only this specific query.
djhi marked this conversation as resolved.
Show resolved Hide resolved

This object updates according to the request state:

Expand Down Expand Up @@ -175,6 +176,8 @@ const UserProfile = ({ record }) => {

In practice, react-admin uses `useQueryWithStore` instead of `useQuery` everywhere, and you should probably do the same in your components. It really improves the User Experience, with only one little drawback: if the data changed on the backend side between two calls for the same query, the user may briefly see outdated data before the screen updates with the up-to-date data.

Just like `useQuery`, `useQueryWithStore` also returns a `¶efetch` function you can call to trigger a refetch. It's different than the `refresh` function returned by `useRefresh` as it won't trigger a refresh of the view, only this specific query.
djhi marked this conversation as resolved.
Show resolved Hide resolved

## `useMutation` Hook

`useQuery` emits the request to the `dataProvider` as soon as the component mounts. To emit the request based on a user action, use the `useMutation` hook instead. This hook takes the same arguments as `useQuery`, but returns a callback that emits the request when executed.
Expand Down
12 changes: 6 additions & 6 deletions packages/ra-core/src/dataProvider/useQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,21 +123,21 @@ const useQuery = (
: [payload, otherOptions]
)
.then(({ data, total }) => {
setState(prev => ({
...prev,
setState({
data,
total,
loading: false,
loaded: true,
}));
refetch,
});
})
.catch(error => {
setState(prev => ({
...prev,
setState({
error,
loading: false,
loaded: false,
}));
refetch,
});
});
}, [
requestSignature,
Expand Down
7 changes: 4 additions & 3 deletions packages/ra-core/src/dataProvider/useQueryWithStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,14 @@ const useQueryWithStore = <State extends ReduxState = ReduxState>(
if (requestSignatureRef.current !== requestSignature) {
// request has changed, reset the loading state
requestSignatureRef.current = requestSignature;
setState(prev => ({
...prev,
setState({
data,
total,
error: null,
loading: true,
loaded: isDataLoaded(data),
}));
refetch,
});
} else if (!isEqual(state.data, data) || state.total !== total) {
// the dataProvider response arrived in the Redux store
if (typeof total !== 'undefined' && isNaN(total)) {
Expand All @@ -183,6 +183,7 @@ const useQueryWithStore = <State extends ReduxState = ReduxState>(
state.total,
total,
isDataLoaded,
refetch,
]);

const dataProvider = useDataProvider();
Expand Down