-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
/
useGetOne.ts
74 lines (70 loc) · 2.63 KB
/
useGetOne.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import get from 'lodash/get';
import {
Identifier,
Record,
ReduxState,
UseDataProviderOptions,
} from '../types';
import useQueryWithStore from './useQueryWithStore';
/**
* Call the dataProvider.getOne() method and return the resolved value
* as well as the loading state.
*
* The return value updates according to the request state:
*
* - start: { loading: true, loaded: false }
* - success: { data: [data from response], loading: false, loaded: true }
* - error: { error: [error from response], loading: false, loaded: true }
*
* This hook will return the cached result when called a second time
* with the same parameters, until the response arrives.
*
* @param resource The resource name, e.g. 'posts'
* @param id The resource identifier, e.g. 123
* @param {Object} options Options object to pass to the dataProvider.
* @param {boolean} options.enabled Flag to conditionally run the query. If it's false, the query will not run
* @param {Function} options.onSuccess Side effect function to be executed upon success, e.g. { onSuccess: { refresh: true } }
* @param {Function} options.onFailure Side effect function to be executed upon failure, e.g. { onFailure: error => notify(error.message) }
*
* @returns The current request state. Destructure as { data, error, loading, loaded }.
*
* @example
*
* import { useGetOne } from 'react-admin';
*
* const UserProfile = ({ record }) => {
* const { data, loading, error } = useGetOne('users', record.id);
* if (loading) { return <Loading />; }
* if (error) { return <p>ERROR</p>; }
* return <div>User {data.username}</div>;
* };
*/
const useGetOne = <RecordType extends Record = Record>(
resource: string,
id: Identifier,
options?: UseDataProviderOptions
): UseGetOneHookValue<RecordType> =>
useQueryWithStore(
{ type: 'getOne', resource, payload: { id } },
options,
(state: ReduxState) => {
if (
// resources are registered
Object.keys(state.admin.resources).length > 0 &&
// no registered resource matching the query
!state.admin.resources[resource]
) {
throw new Error(
`No <Resource> defined for "${resource}". useGetOne() relies on the Redux store, so it cannot work if you don't include a <Resource>.`
);
}
return get(state, ['admin', 'resources', resource, 'data', id]);
}
);
export type UseGetOneHookValue<RecordType extends Record = Record> = {
data?: RecordType;
loading: boolean;
loaded: boolean;
error?: any;
};
export default useGetOne;