Nextjsで sqlite のデータを読み込むときの Path
nextjs(react)の話。
非同期通信の実験のために sqlite を使ったのですが、テーブルを読み込めない原因がわからず半日以上悩みました。
結論を言うと path が違っていたという単純なものです。
filename: ◯◯◯
はプロジェクトルートから見た path を書きましょう、ということだったのですが、なかなか気づかずに彷徨いました。
相対パスだの絶対パスだのはいつまで経っても慣れません。忘れた頃にやられます。
import { NextApiResponse } from 'next';
import sqlite3 from 'sqlite3';
import {open} from 'sqlite';
// members テーブルからデータを取得する
export default async function getMemebers (
response:NextApiResponse
) {
//db へ接続。
const db = await open(
{filename:'./members.db', // ← ここの書き方が間違い、というか実際にファイルを置いている場所とは違うパスになっていた。
driver: sqlite3.Database}
);
const members = await db.all('select * from members');
response.json(members);
}
答えがわかるまでの道のり
api
ディレクトリを用意して、そこに members.tsx
的なコンポーネントを作る。
試しに使うデータは、テーブ名を people にして、
- id: 1, name: John
- id: 2, name: Mike
- …
のようなありがちなものです。
nextjs では通常(設定を特にいじらなければ)、ディレクトリの通りに url も決まるので、この開発作業中にこのページを表示させるには、ブラウザのアドレスバーに、
localhost:3000/api/members
と打ち込めば良いはずです。
ところが、肝心のデータが読み込めない。コンソールには「membersだって?そんなテーブルはありませんよ」と書かれている。
コンポーネントのコードを hello world
的な極めて単純なものに変更すればページは表示されるので members.tsx
ファイルの配置は間違っていない。
問題は sqlite のデータベースを開いて json で返すところになる、はず。
そもそも、 sqlite のデータがきちんと作られていないのでは?
と思われますが、Gui のアプリ(DB Browser for SQLite)でテーブルの中身は確認済み。
試しに nodejs で sqlite のデータを取得するスクリプトファイルを作成して動かすときちんとデータが返ってくる。npm sqlite の Usage に書いてあるようなやつです。
じゃあやっぱり問題は nextjs で書いた members.tsx
ファイルということになります。
async/await も 時間差で console.log に何かを表示させるものに書き換えたりして成功したので問題なし。そうなるともうファイルパスしか直せるところがありません。
db のファイルを様々な場所に配置してみる
members.db
ファイルをひとつ上の階層やルート直下に置いてみたりしてようやく答えが見つかりました。
私は members.db というファイルを members.tsx と同じく、api ディレクトリに置いていたのですが、これが間違いを生んだ原因のようです(ファイルの置き場自体はどこでも良い)。
filename: './members.db'
と書いていながら、その場所にファイルを置いていなかったということです。
filename: './pages/api/members.db'
としなくてはいけなかったのです。
import { NextApiResponse } from 'next';
import sqlite3 from 'sqlite3';
import {open} from 'sqlite';
// members テーブルからデータを取得する
export default async function getMemebers (
response:NextApiResponse
) {
//db へ接続。
const db = await open(
{filename:'./pages/api/members.db', // ← プロジェクトのルートから見た path
driver: sqlite3.Database}
);
const members = await db.all('select * from members');
response.json(members);
}
members.db
というファイルを読み込むのは、node_module
の sqlite
であり、members.tsx
ではない、ということだと思います。
プロジェクトルート(自分のアプリ名が付いているディレクトリ)を基準にして考えなくてはいけなかったということです。
こんなところで躓く人はいるのでしょうか。多分ほとんどいないでしょう。
Reactへ戻る