📝

Next.js+React-admin+PostgreSQLによる開発環境構築

2023/08/20に公開

はじめに

Next.js+React-admin+PostgreSQLで開発するための環境を構築する手順。
基本的にはReact-adminのチュートリアルをベースに進めていく。

https://marmelab.com/react-admin/NextJs.html

Next.jsプロジェクト作成

まずはNext.jsのプロジェクトを作成。

>npx create-next-app@latest

※ 「Would you like to use App Router? (recommended)」について
  「Pages Router」と「App Router」があるらしい。
 今後は「App Router」がおすすめらしいので、今回は「App Router」を選択。

起動

npm run devで起動し、http://localhost:3000/にアクセス。
とりあえず画面は開いた。

React-adminとの統合

react-adminをインストール。
最初のテスト用にra-data-json-serverを使用するので、これもいったんインストール。

>npm add react-admin ra-data-json-server

チュートリアルに従ってsrc/components/AdminApp.jsxのファイルを追加し、src/app/page.tsxのファイルの中身を書き換える。
画面を確認すると、React-adminの管理画面が表示される。

ここまではほぼチュートリアルの通り。

APIルーティング

「Pages Router」の場合はデフォルトで「pages/api」のフォルダが作成されており、ここにAPIを追加すればよかったのだが、「App Router」の場合は少し違うらしい。
詳細は、以下参照。

https://nextjs.org/docs/app/building-your-application/routing/route-handlers

以下のように、api\hello\route.tsのファイルを作成する。

http://localhost:3000/api/helloでアクセスすると、APIからの応答が確認できる。

PostgreSQLとの接続

テスト用に、以下のようなテーブルとデータを作成する。

CREATE TABLE tests (id serial, name text, create_dt timestamptz, note text);
INSERT INTO tests (name, create_dt, note) VALUES ('test1', '2023/01/01','test1-note');
INSERT INTO tests (name, create_dt, note) VALUES ('test2', '2023/01/02','test2-note');

API側で、「pg」を使用してPostgreSQLのテストデータを取得する。

>npm i pg
src\app\api\tests\route.ts
import { NextResponse } from 'next/server'
 
const { Pool } = require('pg');

const pool = new Pool({
  user: process.env.DB_USER || 'postgres',
  password: process.env.DB_PASSWORD || 'postgres',
  host: process.env.DB_HOST || 'localhost',
  port: process.env.DB_PORT || 5432,
  database: process.env.DB_NAME || 'postgres',
  ssl: ((process.env.DB_SSL && process.env.DB_SSL.toLowerCase() == 'true') || false)
    ? { rejectUnauthorized: false } : false,
});

export async function GET() {
  const client = await pool.connect();
  const ret = await client.query('select * from tests', []);
  await client.release(true);

  console.log(ret);

  return NextResponse.json(ret.rows)
}

http://localhost:3000/api/testsでテストデータが取得できることを確認。

画面表示

以下を参考に、simpleRestProviderを使用したリスト表示に切り替える。
https://marmelab.com/react-admin/DataProviders.html

まずはra-data-simple-restをインストール。

>npm i ra-data-simple-rest

リスト表示の定義。

src\components\Tests.jsx
import { List, Datagrid, TextField, DateField } from 'react-admin';

export const TestList = () => (
    <List>
        <Datagrid>
            <TextField source="id" />
            <TextField source="name" />
            <DateField source="create_dt" />
            <TextField source="note" />
        </Datagrid>
    </List>
);

ra-data-json-serverを使用していたところを、ra-data-simple-restに切り替える。

src\components\AdminApp.jsx
"use client"; // only needed if you choose App Router
import { Admin, Resource, ListGuesser, EditGuesser } from "react-admin";
import jsonServerProvider from "ra-data-json-server";
import simpleRestProvider from 'ra-data-simple-rest';

import { TestList } from './Tests';

// const dataProvider = jsonServerProvider("https://jsonplaceholder.typicode.com");
const dataProvider = jsonServerProvider('http://localhost:3000/api/');

const AdminApp = () => (
  <Admin dataProvider={dataProvider}>
    <Resource name="tests" list={TestList} />
  </Admin>
);

export default AdminApp;

画面を更新すると、以下のエラーが発生。

「X-Total-Count」のヘッダーが必要とのこと。
API側でセットする。

src\app\api\tests\route.ts
import { NextResponse } from 'next/server'
 
const { Pool } = require('pg');

const pool = new Pool({
  user: process.env.DB_USER || 'postgres',
  password: process.env.DB_PASSWORD || 'postgres',
  host: process.env.DB_HOST || 'localhost',
  port: process.env.DB_PORT || 5432,
  database: process.env.DB_NAME || 'postgres',
  ssl: ((process.env.DB_SSL && process.env.DB_SSL.toLowerCase() == 'true') || false)
    ? { rejectUnauthorized: false } : false,
});

export async function GET() {
  const client = await pool.connect();
  const ret = await client.query('select * from tests', []);
  await client.release(true);

  console.log(ret);

  const headers = {
    // "Access-Control-Allow-Origin": "*",
    // "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
    // "Access-Control-Allow-Headers": "Content-Type, Authorization",
    "X-Total-Count": ret.rows.length,
  };

  return NextResponse.json(ret.rows, { status: 200, headers: headers })
}

※ 上記ではコメントアウトしているが、別オリジンからのアクセスの場合は"Access-Control-Allow-Origin"なども設定が必要になるはず。

画面表示すると、今度は成功。

まとめ

とりあえずはNext.js+React-adminの統合と、PostgreSQLデータの取得まで。
ソートやページング、追加更新削除などは未実装。。。

Discussion