Refineは、社内の管理画面やダッシュボードのようにCRUDが中心になる画面を、Reactで組むためのフレームワークです。認証・一覧・フォーム・権限といった毎回同じになる処理をフックとして提供し、見た目のライブラリは利用者が選びます。似た立ち位置のreact-adminとは、標準の見た目を持つかどうかと、何が有料かが選定の分かれ目です。この記事では、2026年10月16日時点のnpmレジストリ・GitHub・公式ドキュメントと、手元で動かした結果をもとに、両者の違い、v5の始め方、データ接続、UIの選び方、v4からの移行で壊れる箇所を扱います。
まとめ:RefineとReact-adminの選び分け
結論から書きます。Ant DesignやMantineなど、Material UI以外のUIや既存のデザインシステムに合わせたいならRefine、Material UIで一気に完成形へ近づけたいならreact-adminです。Refineには標準の見た目が無く、最初にUIを選ぶ前提です。react-adminは標準がMaterial UIで、別のUIで組むならヘッドレスのra-coreか、shadcn/ui版のshadcn-admin-kitを使います(react-adminの機能説明)。
版の現在地は次のとおりです。npmで配布されているRefineの@refinedev/coreは5.0.12(2026-04-02公開・MIT)で、TanStack Query v5が必須です。react-adminは5.15.4(2026-09-25公開・MIT)。どちらもReact 18と19に対応します。注意したいのは、RefineのGitHubでは5.1.0と5.2.0の変更が記録されているのに、npmには届いていない点です(後述)。
費用は「何に払うか」が違います。RefineのnpmパッケージはすべてMITで、機能を解放するための有料パッケージはありません。課金対象はAIでアプリを生成するRefine AI(Starterが月0.99ドル・300クレジット、Proが月20ドル・1,500クレジット)と、個別契約のEnterpriseです(Refineの料金ページ)。react-adminは、リアルタイム更新や表の直接編集などを完成済みの有料モジュールとして提供しており、使うには最小のTeamプランで年払い月145ユーロ(開発者2人まで)がかかります(react-admin Enterprise Edition)。
Refineとは|見た目を持たないReactの管理画面フレームワーク
コア・ルーター・UI・データの4層構成
Refineは@refinedev/coreを中心にしたパッケージ群です。コアが提供するのはUI部品ではなくフックで、useListやuseFormを呼ぶと、取得・更新・キャッシュ・エラー処理が済んだ値が返ります。そこにルーター連携(React Router・Next.js・Remix)、UI連携(Ant Design・Material UI・Chakra UI・Mantine)、data provider(バックエンドとの接続部品)を足して1つのアプリにします。npmの週間ダウンロードは@refinedev/coreが255,442件、react-adminが180,445件でした(2026-10-06〜10-12、npm downloads API)。
この構造の利点は、既存プロダクトのデザインシステムをそのまま使えることです。逆に、UI連携を使わずに始めると一覧のテーブルもフォームも自分で書くので、初日の見た目はreact-adminより素朴になります。
開発状況:GitHubは5.2.0、npmは5.0.12のまま
リポジトリ(refinedev/refine、スター35,871)はアーカイブされておらず、10月に入ってもプルリクエストが続いています。ただし配布は止まっています。packages/core/CHANGELOG.mdには5.1.0(認証プロバイダのupdateIdentityとuseUpdateIdentityの追加)と5.2.0(MetaQueryのinterface化、useDataProviderのジェネリクス対応)が載っていますが、npmに公開された最新は5.0.12です。2026-09-10の「version packages」マージ後に走ったReleaseワークフローは、npmへの公開ステップ(Create Release Pull Request or Publish to npm)が失敗で終わっていました。
実務への影響ははっきりしています。GitHubのドキュメントやCHANGELOGで見つけたAPIが、npmの版には入っていないことがあります。手元の5.0.12で確かめると、useUpdatePasswordはあり、useUpdateIdentityは未定義でした。採用時はnpm view @refinedev/core versionで配布版を確かめ、その版の型定義を正にしてください。
react-adminとの違い|UIを固定するか、選べるようにするか
機能の細かい差より先に、標準のUIをどう扱うかで大半が決まります。次に効くのが、無償の範囲でどこまで作れるかです。react-adminそのものの使い方はReact-adminとは?管理画面を最速で作るReactフレームワークの使い方で扱っています。
| 観点 | Refine 5.0.12 | react-admin 5.15.4 |
|---|---|---|
| 標準のUI | なし(UI連携は選択制) | Material UI |
| 別UIの選択肢 | Ant Design / MUI / Chakra UI / Mantine / shadcn/ui | shadcn/ui(shadcn-admin-kit)/ ra-coreで自作 |
| データ層 | TanStack Query v5(必須) | dataProvider+内部でTanStack Query |
| ライセンス | MIT(全npmパッケージ) | MIT(本体のみ) |
| 有料の対象 | Refine AI・Enterprise契約 | 機能モジュール(月145ユーロ〜) |
| アクセス制御 | 無償(accessControlProvider) | 無償(canAccess)+有料ra-rbac |
| React | 18 / 19 | 18 / 19 |
| 直近のnpm公開 | 2026-04-02 | 2026-09-25 |
判断はこうなります。納期が短く、Material UIの見た目でよく、一覧・フォーム・フィルタが揃えば十分ならreact-adminが速いです。Ant DesignやMantineなど、Material UIとshadcn/ui以外のUIに合わせるならRefineが素直です。react-adminでもra-coreで別UIは組めますが、標準部品の厚みはMaterial UI版に集中しています。
react-adminの有料側には、リストの直接編集(Datagrid AG)、関連データの編集(Relationships)、監査ログ(Audit Log)、リアルタイム更新(Realtime)などが入ります。アクセス制御は、5.3からauthProvider.canAccessと<CanAccess>が無償版に入り、有料のra-rbacはその制御を<Datagrid>や<SimpleForm>などの部品単位へ広げる位置づけに変わりました(marmelabの2025年1月の更新記事)。無償版のフックで同等の機能を自作することもできるため、見積もりは「有料モジュールの購読費」と「自作の工数」の比較になります。本体がMITだからといって、表の直接編集や同時編集の反映まで無料の部品で揃うわけではありません。RefineはaccessControlProviderとuseCanをコアに持ち、追加料金はかかりません。
Refineの始め方|create-refine-appと既存プロジェクトへの追加
create-refine-appによる新規作成
最短はnpm create refine-app@latest my-appです。対話でフレームワーク(Vite・Next.js・Remix)、data provider、UI、認証の有無を選ぶと、その組み合わせに応じた構成で生成されます。ログイン画面は認証を選んだときだけ、サンプルのリソースはサンプルを選んだときだけ入ります。生成後は同梱の@refinedev/cliで、リソースの追加(npm run refine -- add resource orders --actions list,createのように画面を絞れる)と、UI連携の部品を自分のコードへ書き出すswizzle(npm run refine swizzle)ができます。
Qiitaなどで紹介されているInferencer(データから一覧・編集画面のコードを推測生成する仕組み)は、v5対応の@refinedev/inferencer 7.0.0が最新です。ただし7.0.0以下には、APIが返すフィールド名をエスケープせずに生成コードへ埋め込み、開発者のブラウザで任意のJavaScriptが実行されうる脆弱性(CVE-2026-92784、CVSS 4.0で7.7)が2026-09-16に公表されています(VulnCheckの勧告)。対応するIssue #7556は2026-10-16時点で未解決で、修正版は出ていません。信頼できない外部APIをInferencerに読ませないこと、生成コードは貼り付けたらInferencerを外すことが前提です。peerDependenciesもantd ^5.0.3、@mui/material ^6.1.7のままです。
既存のReact・Next.jsプロジェクトへの追加
既存プロジェクトでは、必要なパッケージだけを入れます。データ層はTanStack Query v5がそのまま使われるので、キャッシュの挙動を細かく制御したい場面ではTanStack Queryとは?React Queryとの違い・v5の使い方と脆弱性対策の内容がそのまま効きます。
# react / react-dom は 18 か 19 が別途必要
npm install @refinedev/core@5 @tanstack/react-query@5
# React Router 7 系と組む場合
npm install @refinedev/react-router@2 react-router@7
react-router@7と版を明示しているのは、@refinedev/react-router 2.0.4のpeerがreact-router ^7.0.2で、npmの最新は8.4.0だからです。版を付けずに入れると範囲外の8系が入ります。
Next.jsでは@refinedev/nextjs-router(7.0.5)を使います。<Refine>はReactのcontextとstateに依存するため、App Routerではクライアントコンポーネント("use client")に置く必要があります。サーバーコンポーネントでは<Refine>のフックは使えませんが、data providerのメソッドは普通の非同期関数として呼べます(公式のNext.js連携ガイド)。次の例はnpm install @refinedev/simple-restを追加し、接続先のURLを自分のAPIに置き換えて使います。Next.js自体の構成はNext.jsとは?16系App Routerで最小アプリを動かす手順と採用判断を参照してください。
// app/orders/page.tsx(サーバーコンポーネント)
import dataProvider from "@refinedev/simple-rest";
export default async function Orders() {
const { data, total } = await dataProvider("https://api.example.com").getList({
resource: "orders",
pagination: { currentPage: 1, pageSize: 10 },
});
return <p>{total}件中 {data.length}件を表示</p>;
}
Pages Routerなら、getServerSidePropsで取ったデータをフックのqueryOptions.initialDataに渡します。動的なIDを含む編集・詳細画面は静的生成と相性が悪いため、管理画面ではSSRかクライアント描画を前提にしてください。
データ接続の設計|公式data providerの範囲と、自作が必要になる場面
公式のdata providerのドキュメントが公式として挙げるのは、Simple REST、GraphQL、NestJS CRUD、Nestjs-Query、Airtable、Strapi(v4含む)、Supabase、Hasura、Appwrite、Medusaです。Firebase、Directus、PocketBase、PostgRESTなどはコミュニティ製として別枠で載っています。
AWS Amplifyは、公式ドキュメントの公式・コミュニティどちらの一覧にも載っていません。「RefineとAmplifyは相性が良い」という説明を見かけますが、AmplifyのGraphQL APIにつなぐなら、GraphQLパッケージにクエリを渡すか自作することになります。Firebaseもコミュニティ製なので、更新が止まっていないかを採用前に確かめてください。
自作するときに必須なのは、一覧取得・単体取得・作成・更新・削除とAPIのURLを返すメソッドで、後述のuseCustomを使うならcustomも要ります。次の実装は最小例で、フィルタ・ソートやpagination.mode: "off"、customのクエリやヘッダには対応していません。使うAPIの仕様に合わせて引数をURLへ変換する処理を足してください。TypeScript 7.0.2のstrictで型エラーが出ないことと、403や500を返すモックでstatusCode付きのエラーになり、204を返す削除で落ちないことを確かめています。
import type { DataProvider, HttpError } from "@refinedev/core";
// 2xx以外は statusCode 付きで throw する(Refine が通知・認証エラー処理に使う)
const request = async (url: string, init?: RequestInit) => {
const res = await fetch(url, init);
if (!res.ok) {
const error: HttpError = { message: res.statusText || `HTTP ${res.status}`, statusCode: res.status };
throw error;
}
return res;
};
const json = (method: string, body: unknown): RequestInit => ({
method,
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
export const dataProvider = (apiUrl: string): DataProvider => ({
getList: async ({ resource, pagination }) => {
// v5 では pagination.current が currentPage に改名された
const { currentPage = 1, pageSize = 10 } = pagination ?? {};
const res = await request(`${apiUrl}/${resource}?_page=${currentPage}&_limit=${pageSize}`);
return { data: await res.json(), total: Number(res.headers.get("x-total-count") ?? 0) };
},
getOne: async ({ resource, id }) => {
const res = await request(`${apiUrl}/${resource}/${id}`);
return { data: await res.json() };
},
create: async ({ resource, variables }) => {
const res = await request(`${apiUrl}/${resource}`, json("POST", variables));
return { data: await res.json() };
},
update: async ({ resource, id, variables }) => {
const res = await request(`${apiUrl}/${resource}/${id}`, json("PATCH", variables));
return { data: await res.json() };
},
deleteOne: async ({ resource, id }) => {
const res = await request(`${apiUrl}/${resource}/${id}`, { method: "DELETE" });
// 204 No Content は本文が無いので JSON を読まない
return { data: res.status === 204 ? ({ id } as any) : await res.json() }; // TData は呼び出し側の型
},
// useCustom(集計APIなど)を使うなら必要
custom: async ({ url, method }) => {
const res = await request(url, { method: method.toUpperCase() });
return { data: await res.json() };
},
getApiUrl: () => apiUrl,
});
jsdom上でこのdata providerにuseList({ resource: "orders" })だけを渡すと、getListが受け取ったpaginationは{"currentPage":1,"pageSize":10,"mode":"server"}でした。何も指定しなければ1ページ10件のサーバー側ページングになります。2xx以外をthrowしないと、403で拒否された作成も成功として画面に通知されます。返すtotalはページャの総件数に使われるので、ヘッダで総件数を返さないAPIだと最終ページが分かりません。バックエンドの仕様を先に確かめておくと手戻りがありません。
CRUD画面とダッシュボード|resources登録とフックの対応
一覧画面の実装とresourcesの登録
resourcesは、リソース名と一覧・作成・編集・詳細のパスを対応づける宣言です。ルートそのものは作られないので、画面は<Routes>に自分で定義します。各画面ではフックを呼ぶだけで、取得とキャッシュはコアが持ちます。v5のデータフックは、正規化した値をresult、TanStack Queryの状態をqueryにまとめて返します。次の例は一覧画面だけを実装したもので、接続先は前節のdata providerが前提です。
import { Refine, useList } from "@refinedev/core";
import routerProvider from "@refinedev/react-router";
import { BrowserRouter, Routes, Route } from "react-router";
import { dataProvider } from "./dataProvider";
type Order = { id: number; title: string };
const OrderList = () => {
const { result, query } = useList<Order>({ resource: "orders" });
if (query.isLoading) return <p>loading</p>;
if (query.isError) return <p>取得に失敗しました</p>;
return <ul>{result.data.map((o) => <li key={o.id}>{o.title}</li>)}</ul>;
};
export const App = () => (
<BrowserRouter>
<Refine
dataProvider={dataProvider("https://api.example.com")}
routerProvider={routerProvider}
resources={[{ name: "orders", list: "/orders" }]}
>
<Routes>
<Route path="/orders" element={<OrderList />} />
</Routes>
</Refine>
</BrowserRouter>
);
フォームを本格的に組むなら@refinedev/react-hook-form(5.0.4、peerはreact-hook-form ^7.57.0)でuseFormを使います。バリデーションの書き方はReact Hook Formとは?使い方・バリデーション・v7の書き方を実例で解説と同じです。
ダッシュボード画面の作り方
売上推移や進捗率のような集計値は、特定のリソースの一覧ではありません。resourcesに登録せず独立したルートとして置き、useCustomで集計APIを呼びます。data providerにcustomが無いと呼べません。resourcesに登録したものはuseMenuのメニュー項目に並ぶので、集計用の疑似リソースを足すと、meta.hideで隠す手間が増えます。
同じ集計を複数のウィジェットで使っても、同時に表示するならリクエストは1回です。同じURL・メソッド・パラメータでuseCustomを呼ぶウィジェットを3つ同時にマウントしたところ、data providerのcustomが呼ばれたのは1回でした。同じQueryClientの中でクエリキーが一致すると、TanStack Queryが進行中の取得を共有するためです。取得済みのデータが古くなった後に別のウィジェットを表示した場合や、ウィンドウへのフォーカスが戻った場合は再取得されます(TanStack Queryの既定動作)。公式リポジトリのexamplesにはCRM(app-crm・app-crm-minimal)があり、ダッシュボードの組み方の実例として読めます。画面の情報設計そのものは業務システムの画面デザイン|実装者向けUI設計パターンとライブラリ選定のパターンがそのまま当てはまります。
UIの選び方|公式UIパッケージとRefine UI(shadcn/ui)
公式UIパッケージが要求する版
Refineの公式UIパッケージは、UIライブラリの最新メジャーに追随していません。npmのpeerDependenciesは次のとおりです(2026-10-16時点)。
| Refineパッケージ | 版 | peerが要求する版 | UIライブラリ最新 |
|---|---|---|---|
| @refinedev/antd | 6.0.3 | antd ^5.23.0 | antd 6.6.6 |
| @refinedev/mui | 8.0.2 | @mui/material ^6.1.7 | @mui/material 9.5.0 |
| @refinedev/chakra-ui | 3.0.2 | @chakra-ui/react ^2.5.1 | @chakra-ui/react 3.37.0 |
| @refinedev/mantine | 3.0.2 | @mantine/core ^5.10.4 | @mantine/core 9.7.2 |
公式UIパッケージを採用すると、使えるUIライブラリがpeerDependenciesの範囲(antdなら5系)に縛られます。厄介なのは、警告で止まらない場合があることです。npm 11.17.0でantd@6と@refinedev/antd@6を同時に入れるとエラーにならず、ルートにantd 6.6.6、@refinedev/antdの配下にantd 5.29.3が入りました。antdが2つ同居し、Refineのレイアウトや表はantd 5で描画されます。アプリ側のantd 6のConfigProviderやテーマはRefineの部品に届きません。npm ls antdで二重になっていないか確かめてください。Ant Design 6対応のプルリクエスト(#7625・#7629)は2026年10月時点で未マージです。
UIライブラリの最新版を使いたいなら、公式UIパッケージは採用せずコアだけで組むのが安全です。antd 6の変更点はAnt Design(antd)とは?Reactでの使い方・日本語化・v6の変更点【6.6対応】、MUI 9系はMaterial UIとは:v9系の導入からGrid・テーマ設定までコード付きで解説で扱っています。
Refine UI:shadcn/uiレジストリからの部品導入
「Refine UI」はnpmパッケージではなく、shadcn/uiのCLIで取り込む部品のレジストリです。データテーブル、一覧・編集のビュー、サインイン画面、レイアウトなど13点が公開されており、コードは自分のプロジェクトにコピーされます。npmパッケージのpeerDependenciesに縛られず、取り込んだコードを直接直せる点が公式UIパッケージとの違いです。その代わり、Radix UIやTanStack Tableなど取り込んだ依存の更新は自分で管理します。
npx shadcn@latest add https://ui.refine.dev/r/data-table.json
データテーブルは@refinedev/react-table(TanStack Table)のuseTableと組み合わせ、サーバー側のソート・フィルタ・ページングにつながります。Tailwind CSSとshadcn/uiの導入が前提なので、先にshadcn/uiとは?読み方・導入手順とBase UI既定化の変更点をReact開発者向けに解説の手順でプロジェクトを整えておきます。
v4からv5への移行で壊れるもの
@refinedev/coreのv5.0.0は2025-09-03に公開されました。4系最終の4.58.0は前日の2025-09-02です。公式の移行ガイドは、まずnpx @refinedev/codemod@latest refine4-to-refine5での自動変換を勧めています。前提としてTanStack Queryをv5へ上げる必要があり、v4のままでは動きません。
| v4 | v5 |
|---|---|
| useNavigation の push / replace / goBack | useGo / useBack |
| useResource | useResourceParams |
| pagination.current | pagination.currentPage |
| queryResult / tableQueryResult | query / tableQuery |
| metaData | meta |
| queryKeys | keys |
| ThemedLayoutV2(各UIパッケージ) | ThemedLayout |
| ITreeMenu | TreeMenuItem |
| legacyAuthProvider / legacyRouterProvider | 削除(新形式へ) |
よく誤解されるのがuseNavigationです。v5で消えたのはpush・replace・goBackの3つで、フック自体は残っています。5.0.12の型定義では、list・create・edit・showとそれぞれのURLを返す関数が今も使えます。codemodはフックの戻り値を分割代入している素直な書き方は変換しますが、条件分岐の中や独自のラッパー越しの呼び出しは取りこぼすと、移行ガイド自身が書いています。変換後は型検査を通し、isLoadingからisPendingへ変わった更新系の状態も目で確かめてください。
Refineを選ばないほうがよい場面
- 一覧とフォームの型が繰り返さない小規模な管理画面。共通化できる処理が少ないと、resourcesやプロバイダの設定が素直にfetchを書く手間を上回ります。
- CRUDではない画面が主体。ワークフロー承認や複雑な集計が中心なら、Refineの型に合わせるほうが遠回りです。
- UIライブラリを最新メジャーで使う必要があり、コアだけで組む余力もない。公式UIパッケージのpeerDependenciesは、antd・MUI・Chakra UI・Mantineのいずれも最新メジャーを含みません。
- 配布の止まり方を許容できない。npmの最新が半年更新されていない状態は、2026年9月だけで3回公開されたreact-adminと比べて明確な差です。修正をフォークで当てる覚悟がないなら、react-adminのほうが安全です。
逆に、扱うリソースが多く、一覧・絞り込み・編集フォームが同じ形で繰り返し出てきて、認証と権限も必要という条件では、Refineの記述量の削減が効きます。判断の目安は画面数ではなく、data providerとフックで共通化できる処理がどれだけあるかです。管理画面を含む業務システムを外部に任せる場合は、基幹システム開発として要件定義から相談できます。
よくある質問
Refineとは何ですか?
Reactで社内管理画面やダッシュボードなどCRUD中心の画面を作るためのフレームワークです。データ取得・認証・権限・ルーティングをフックとして提供し、見た目は利用者が選びます。2026年10月16日時点、npmの最新は@refinedev/core 5.0.12です。
Refineは無料で使えますか?
使えます。npmのパッケージはすべてMITライセンスで、機能制限のある有料版はありません。有料なのはAIでアプリを生成するRefine AIとEnterprise契約です。react-adminも本体はMITで基本のアクセス制御(canAccess)は無償ですが、リアルタイム更新や表の直接編集を部品として使うには有料のEnterprise Editionが要ります。
Refineとreact-adminはどちらを選ぶべきですか?
Material UIで早く形にしたいならreact-admin、Ant DesignやMantineなど別のUIに合わせたいならRefineです。ほかに、表の直接編集やリアルタイム更新のような有料モジュールが要るか、npmの更新頻度を許容できるかで判断します。
RefineはNext.jsで使えますか?
使えます。@refinedev/nextjs-routerを使い、App Routerでは<Refine>をクライアントコンポーネントに置きます。サーバーコンポーネントではdata providerのメソッドを直接呼んでデータを取れます。
Refineはどのバックエンドにつなげられますか?
公式のdata providerはSimple REST、GraphQL、NestJS CRUD、Nestjs-Query、Airtable、Strapi、Supabase、Hasura、Appwrite、Medusaです。FirebaseやPocketBaseはコミュニティ製で、公式ドキュメントの一覧(公式・コミュニティ)にAWS Amplify用は載っていません。それ以外のAPIは、一覧・単体取得・作成・更新・削除のメソッドを持つdata providerを自作してつなぎます。