Expo × Reactotron でデバッグ環境を整備する:expo-sqlite の静かなバグも可視化できた
console.log だけでは追いきれない Expo アプリの挙動を Reactotron で可視化した。expo-sqlite の NULL/0 型バグなど、ログに出ないバグも見つけられるようになった。
console.log だけで Expo アプリの DB 周りを追っていたら限界が来た。Reactotron を入れたら、console.log では見えなかった「型の違い」が一目で分かるようになり、放置していたバグが見つかった。この記事は、セットアップの最短手順と、実際に効いた使い方に絞る。
Reactotron で何が見えるか
Reactotron は React Native / Expo 向けのデバッグツールで、Mac/Windows のデスクトップアプリとして動く。console.log との違いは、流したオブジェクトをツリーで展開して型ごと確認できること。null と 0、undefined と空文字のように、ターミナルだと同じに見えてしまう値の差が、画面上ではっきり分かれる。DB に何を渡して何が返ったかを追うのに向いている。
セットアップ(最短)
npm install --save-dev reactotron-react-native
reactotron-core-client は reactotron-react-native の依存として一緒に入るので、明示的に入れる必要はない。
設定ファイルを1つ作る:
// ReactotronConfig.ts
import Reactotron from 'reactotron-react-native';
if (__DEV__) {
Reactotron
.configure({ name: 'My App' })
.useReactNative()
.connect();
}
エントリポイントの先頭で読み込む:
// App.tsx
if (__DEV__) {
require('./ReactotronConfig');
}
あとはデスクトップアプリ(releases)を起動した状態で npx expo start すれば接続される。ここまでは公式どおりで、詰まる箇所はほぼない。本題は次から。
DB 操作を Reactotron に流す
expo-sqlite のクエリ実行をラップして、渡した値と返り値をそのまま流す。これだけで INSERT / UPDATE のたびに「何を入れて何が返ったか」が画面に並ぶ。
import Reactotron from 'reactotron-react-native';
import type { SQLiteDatabase } from 'expo-sqlite';
function runQuery(db: SQLiteDatabase, sql: string, params: unknown[]) {
const result = db.runSync(sql, params);
if (__DEV__) {
Reactotron.log({ sql, params, result });
}
return result;
}
Reactotron.log() はそのまま呼べる。オプショナルチェーン(?.)を付けたくなるが、__DEV__ で囲んで接続済みの前提なら不要だ。
これで見つかったバグ:NULL と 0 のすり替わり
入れた一番の収穫がこれだった。console.log では正常に見えていたのに、Reactotron で params を展開したら、0 を入れているつもりのカラムに null が渡っていた。undefined が混ざり込み、それが SQLite 側で null として保存されていた。
// undefined のまま渡すと null として保存される
db.runSync('UPDATE records SET count = ?', [someValue]); // someValue が undefined のとき
// デフォルト値を明示すれば 0 が入る
db.runSync('UPDATE records SET count = ?', [someValue ?? 0]);
ターミナルだと null も 0 も同じ「0」に見えてしまい、型の違いに気づけない。Reactotron でツリー展開すると null は null として表示されるので、ここで初めて差が見えた。console.log から乗り換える価値があったのは、この一点に尽きる。
補足
__DEV__で囲んでいるので、設定ごと本番ビルドには入らない。- 実機で使う場合はアプリと PC が同じ Wi-Fi にいる必要がある。シミュレーターなら気にしなくていい。