mcpField
R
react-admin

react-admin

github.com/marmelab開発27.0k216 回インストール今日更新
リポジトリ

react-admin について

react-adminは、React-adminを使ってRESTまたはGraphQL API上にシングルページアプリを構築するための開発ガイドです。プロバイダー、フック、ルーティング、データ操作、認可、フォームを扱い、既存の抽象機能の活用を促します。

主な機能

  1. 01プロバイダー経由のAPIアクセス
  2. 02データ取得・変更フック
  3. 03コンテキスト・コントローラーフック
  4. 04CRUDとカスタムルーティング
  5. 05認証とアクセス制御
  6. 06フォームと関連レコード項目

活用シーン

  1. 01RESTまたはGraphQL管理アプリの構築
  2. 02リソース向けCRUDページの追加
  3. 03プロバイダー経由のAPIデータ処理
  4. 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を優先してください

コメント