useGetOne
This hook calls dataProvider.getOne() when the component mounts. It queries the data provider for a single record, based on its id.
Syntax
const { data, isPending, error, refetch } = useGetOne(
resource,
{ id, meta },
options
);
The meta argument is optional. It can be anything you want to pass to the data provider, e.g. a list of fields to show in the result.
The options parameter is optional, and is passed to react-queryβs useQuery hook. It may contain the following options:
cacheTimeenabledinitialDatainitialDataUpdatedAtisDataEqualkeepPreviousDatametanotifyOnChangePropsnotifyOnChangePropsExclusionsonErroronSettledonSuccessplaceholderDataqueryKeyHashFnrefetchIntervalrefetchIntervalInBackgroundrefetchOnMountrefetchOnReconnectrefetchOnWindowFocusretryretryOnMountretryDelayselectstaleTimestructuralSharingsuspenseuseErrorBoundary
Check react-queryβs useQuery hook documentation for details on each of these options.
The react-query query key for this hook is [resource, 'getOne', { id: String(id), meta }].
Usage
Call useGetOne in a component to query the data provider for a single record, based on its id.
import { useGetOne, useRecordContext } from 'react-admin';
const UserProfile = () => {
const record = useRecordContext();
const { data: user, isPending, error } = useGetOne('users', { id: record.userId });
if (isPending) { return <Loading />; }
if (error) { return <p>ERROR</p>; }
return <div>User {user.username}</div>;
};
Aggregating getOne Calls
If you use useGetOne several times on a page for the same resource, replace the useGetOne call by useGetManyAggregate, as it de-duplicates and aggregates queries for a single record into one batch query for many records.
-import { useGetOne, useRecordContext } from 'react-admin';
+import { useGetManyAggregate, useRecordContext } from 'react-admin';
const UserProfile = () => {
const record = useRecordContext();
- const { data: user, isPending, error } = useGetOne('users', { id: record.userId });
+ const { data: users, isPending, error } = useGetManyAggregate('users', { ids: [record.userId] });
if (isPending) { return <Loading />; }
if (error) { return <p>ERROR</p>; }
- return <div>User {user.username}</div>;
+ return <div>User {users[0].username}</div>;
};
This results in less calls to the dataProvider. For instance, if the <UserProfile> component above is rendered in a <Datagrid>, it will only make one call to dataProvider.getMany() for the entire list instead of one call to dataProvider.getOne() per row.
As useGetManyAggregate is often used to fetch references, react-admin exposes a useReference hook, which avoids doing the array conversion manually. Itβs an application hook rather than a data provider hook, so its syntax is a bit different. Prefer useReference to useGetManyAggregate when you use useGetOne to fetch a reference.
-import { useGetOne, useRecordContext } from 'react-admin';
+import { useReference, useRecordContext } from 'react-admin';
const UserProfile = () => {
const record = useRecordContext();
- const { data: user, isPending, error } = useGetOne('users', { id: record.userId });
+ const { referenceRecord: user, isPending, error } = useReference({ reference: 'users', id: record.userId });
if (isPending) { return <Loading />; }
if (error) { return <p>ERROR</p>; }
return <div>User {user.username}</div>;
};
Refreshing the Record
If you want to refresh the record, use the refetch function returned by the hook.
import { useGetOne } from 'react-admin';
const UserProfile = ({ userId }) => {
const { data, isPending, error, refetch } = useGetOne('users', { id: userId });
if (isPending) { return <Loading />; }
if (error) { return <p>ERROR</p>; }
return (
<>
<div>User {data.username}</div>
<button onClick={() => refetch()}>Refresh</button>
</>
);
};
Live Updates
If you want to subscribe to live updates on the record (topic: resource/[resource]/[id]), use the useGetOneLive hook instead.
-import { useGetOne, useRecordContext } from 'react-admin';
+import { useRecordContext } from 'react-admin';
+import { useGetOneLive } from '@react-admin/ra-realtime';
const UserProfile = () => {
const record = useRecordContext();
- const { data, isPending, error } = useGetOne('users', { id: record.userId });
+ const { data, isPending, error } = useGetOneLive('users', { id: record.userId });
if (isPending) {
return <Loading />;
}
if (error) {
return <p>ERROR</p>;
}
return <div>User {data.username}</div>;
};
TypeScript
The useGetOne hook accepts a generic parameter for the record type:
import { useGetOne, useRecordContext } from 'react-admin';
type Ticket = {
id: number;
userId: string;
message: string;
};
type User = {
id: number;
username: string;
}
const UserProfile = () => {
const ticket = useRecordContext<Ticket>();
const { data: user, isPending, error } = useGetOne<User>('users', { id: ticket.userId });
if (isPending) { return <Loading />; }
if (error) { return <p>ERROR</p>; }
// TypeScript knows that user is of type User
return <div>User {user.username}</div>;
};
