react-admin について
react-adminは、React-adminを使ってRESTまたはGraphQL API上にシングルページアプリを構築するための開発ガイドです。プロバイダー、フック、ルーティング、データ操作、認可、フォームを扱い、既存の抽象機能の活用を促します。
主な機能
- 01プロバイダー経由のAPIアクセス
- 02データ取得・変更フック
- 03コンテキスト・コントローラーフック
- 04CRUDとカスタムルーティング
- 05認証とアクセス制御
- 06フォームと関連レコード項目
活用シーン
- 01RESTまたはGraphQL管理アプリの構築
- 02リソース向けCRUDページの追加
- 03プロバイダー経由のAPIデータ処理
- 04認可とフォームの実装
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ marmelab/ react-admin --skill react-adminインストール後、Claude Code で/react-adminを入力して読み込まれたか確認します。
詳細
React-Admin 開発ガイド
React-admin は、REST/GraphQL API の上にシングルページアプリケーションを構築するためのフレームワークです。React Query、react-hook-form、react-router、Material UI を基盤としています。150 以上のコンポーネントと数十種類のフックを提供します。カスタムコードを書く前に、必ず react-admin がタスクに対応するコンポーネントやフックをすでに提供していないか確認してください。完全なドキュメントはこちらです:https://marmelab.com/react-admin/doc/
プロバイダー(バックエンドの抽象化)
React-admin は API を直接呼び出しません。すべての通信は プロバイダー を経由します。プロバイダーは、react-admin の標準化された呼び出しを、API 固有のリクエストに変換するアダプターです。主なプロバイダーは次の 3 つです。
- dataProvider:すべての CRUD 操作(
getList、getOne、create、update、delete、getMany、getManyReference、updateMany、deleteMany)。DataProviders と 50 以上の既存アダプター を参照してください。 - authProvider:認証と認可。Authentication を参照してください。
- i18nProvider:翻訳(
translate、changeLocale、getLocale)。
重要なルール:コンポーネント内で fetch、axios、直接の HTTP 呼び出しを使用しないでください。必ず data provider のフックを使用してください。これにより、適切なキャッシュ、読み込み状態、エラー処理、認証、楽観的レンダリングが実現します。
コンポジション(巨大なコンポーネントを作らない)
React-admin は、設定よりもコンポジションを重視します。多数の props を設定するのではなく、子コンポーネントを渡して動作をオーバーライドしてください。
<Edit actions={<MyCustomActions />}>
<SimpleForm>
<TextInput source="title" />
</SimpleForm>
</Edit>
レイアウトをカスタマイズするには、カスタムレイアウトコンポーネントを <Admin layout={MyLayout}> に渡します。メニューをカスタマイズするには、<Layout menu={MyMenu}> に渡します。このように連鎖させる設計になっています。Architecture を参照してください。
コンテキスト:プッシュではなくプル
React-admin のコンポーネントは、React コンテキストを通じて子孫コンポーネントにデータを公開します。props を下位に渡すのではなく、フックを使ってデータにアクセスしてください。
useRecordContext()— Show/Edit/Create ビューの現在のレコード。useRecordContext を参照してください。useListContext()— List ビューのリストデータ、フィルター、ページネーション、並べ替え。useListContext を参照してください。useShowContext()、useEditContext()、useCreateContext()— 詳細ビューのページレベルの状態。useTranslate()— i18nProvider の翻訳関数。useGetIdentity()— authProvider から取得する現在のユーザー。
カスタムコンポーネントよりフックを使う
react-admin コンポーネントの UI が要件に合わない場合は、一から作るのではなく、基盤となるフックを使用してください。コントローラーフック(use*Controller という名前)は、UI を含まずにロジックをすべて提供します。
useListController()— リストの取得、フィルタリング、ページネーションのロジックuseEditController()— 編集フォームのデータ取得と送信のロジックuseShowController()— 詳細ページのデータ取得ロジック
ルーティング
<Resource> は CRUD ルート(/posts、/posts/create、/posts/:id/edit、/posts/:id/show)を自動的に宣言します。CRUD 以外のページには <CustomRoutes> を使用してください。リソース URL の構築には useCreatePath() を、ナビゲーションには react-admin の <Link> を使用してください。デフォルトのルーターは react-router(HashRouter)ですが、routerProvider を介して TanStack Router もサポートされています。Routing を参照してください。
データ取得
クエリーフック(データの読み取り)
const { data, total, isPending, error } = useGetList('posts', {
pagination: { page: 1, perPage: 25 },
sort: { field: 'created_at', order: 'DESC' },
filter: { status: 'published' },
});
const { data: record, isPending } = useGetOne('posts', { id: 123 });
const { data: records } = useGetMany('posts', { ids: [1, 2, 3] });
const { data, total } = useGetManyReference('comments', {
target: 'post_id', id: 123,
pagination: { page: 1, perPage: 25 },
});
useGetList、useGetOne を参照してください。
ミューテーションフック(データの書き込み)
すべてのミューテーションは[mutate, state]を返します。次のミューテーションモードをサポートしています。
- pessimistic(デフォルト):サーバーからの応答を待ってから、UI を更新します。
- optimistic:UI をすぐに更新し、サーバーエラーが発生した場合は元に戻します。
- undoable:UI を更新し、取り消し通知を表示して、遅延後に確定します。
const [create, { isPending }] = useCreate();
const [update] = useUpdate();
const [deleteOne] = useDelete();
// Call with resource and params
create('posts', { data: { title: 'Hello' } });
update('posts', { id: 1, data: { title: 'Updated' }, previousData: record });
deleteOne('posts', { id: 1, previousData: record });
即座に UI を反映するには、mutationMode: 'optimistic'または'undoable'を渡します。useCreate、useUpdateを参照してください。
認証と認可
const authProvider = {
login: ({ username, password }) => Promise<void>,
logout: () => Promise<void>,
checkAuth: () => Promise<void>, // Verify credentials are valid
checkError: (error) => Promise<void>, // Detect auth errors from API responses
getIdentity: () => Promise<{ id, fullName, avatar }>,
getPermissions: () => Promise<any>,
canAccess: ({ resource, action, record }) => Promise<boolean>, // RBAC
};
各 auth provider メソッドには、対応するフックがあります(例:useGetIdentity()、useCanAccess())。
- カスタムルートはデフォルトで公開されています。 ログインを必須にするには、
<Authenticated>で囲むか、useAuthenticated()を呼び出してください。Authenticatedを参照してください。 - 認可は個々のコンポーネントではなく、
authProvider.canAccess()に集約してください。権限の確認にはuseCanAccess()を使用します。useCanAccessとAuthRBACを参照してください。 - dataProvider はリクエストに認証情報(Bearer トークン、Cookie)を含める必要があります。ログインは authProvider が処理しますが、API 呼び出しは dataProvider が処理します。データプロバイダーの設定で
httpClientを設定してください。
エンティティ間のリレーションシップ
ページに必要なすべてのデータ(リレーションシップを含む)を事前に取得するのはアンチパターンです。代わりに、参照フィールドと入力を使用して、関連レコードを必要に応じて取得してください。
関連レコードの表示(フィールド)
{/* Show a the company of the current record based on its company_id */}
<ReferenceField source="company_id" reference="companies" />
{/* Show a list of related records (reverse FK) */}
<ReferenceManyField reference="comments" target="post_id">
<DataTable>
<TextField source="body" />
<DateField source="created_at" />
</DataTable>
</ReferenceManyField>
{/* Show multiple referenced records (array of IDs) */}
<ReferenceArrayField source="tag_ids" reference="tags">
<SingleFieldList>
<ChipField source="name" />
</SingleFieldList>
</ReferenceArrayField>
ReferenceField、ReferenceManyField、ReferenceArrayFieldを参照してください。
関連レコードの編集(入力)
{/* Select from another resource (FK) */}
<ReferenceInput source="company_id" reference="companies" />
{/* Multi-select from another resource (array of IDs) */}
<ReferenceArrayInput source="tag_ids" reference="tags" />
ReferenceInput、ReferenceArrayInputを参照してください。
フォーム
React-admin のフォームは react-hook-form を基盤としています。単一列のレイアウトには<SimpleForm>を、複数タブのレイアウトには<TabbedForm>を使用してください。SimpleForm、TabbedFormを参照してください。
入力コンポーネントにはバリデーターを渡します:required()、minLength(min)、maxLength(max)、minValue(min)、maxValue(max)、number()、email()、regex(pattern, message)、またはエラー文字列を返すカスタム関数です。
<TextInput source="title" validate={[required(), minLength(3)]} />
フィールドの値に応じて変化する動的なフォームを作成するには、RHF のuseWatch()を使用してください。
リソース定義
インポートを整理するため、リソースコンポーネントを index ファイルにまとめます。
// posts/index.ts
export default {
list: PostList,
create: PostCreate,
edit: PostEdit,
icon: PostIcon,
recordRepresentation: (record) => record.title, // How records appear in references
};
Resource、RecordRepresentationを参照してください。
カスタムデータプロバイダーメソッド
ドメイン固有のメソッドで dataProvider を拡張します。
const dataProvider = {
...baseDataProvider,
archivePost: async (id) => { /* custom logic */ },
};
// Call via useDataProvider and useQuery:
// const dp = useDataProvider();
// const { data } = useQuery(['archivePost', id], () => dp.archivePost(id));
クライアント状態の永続化(Store)
ユーザー設定(テーマ、列の表示設定、保存済みフィルター)の永続化にはuseStore()を使用してください。
const [theme, setTheme] = useStore('theme', 'light');
Storeを参照してください。
通知、リダイレクト、更新
const notify = useNotify();
const redirect = useRedirect();
const refresh = useRefresh();
notify('Record saved', { type: 'success' });
redirect('list', 'posts'); // Navigate to /posts
redirect('edit', 'posts', 123); // Navigate to /posts/123
refresh(); // Invalidate all queries
非推奨
- Datagrid の代わりに DataTable を使用してください
- 認可チェックには
<CanAccess>とuseCanAccessを優先してください