49
53

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

React Native & Expo デバッグ方法いろいろ

Last updated at Posted at 2020-08-16

私がシステム開発(環境整備)をする上でもっとも重要視しているのが**「デバッグ」**です。
プログラミングを始めたばかりのころはデバッグの重要性を知らず、
エラーやバグの原因が特定できずなんども挫折してしまった経験があります。

ただ、その重要性を知っていても、未経験の言語だったりフレームワークだったりすると設定が意外と難しかったり、ベストプラクティスが決まっておらず案外はまってしまったりするのではないでしょうか。

今回はReact Native + Expo + Typescriptでのアプリの開発を通して、様々なデバッグ方法を試してみたので設定方法も含めて残しておこうと思います。

今後React Nativeを使ってネイティブアプリ開発を始めようと考えている方の一番最初のハードルを取り払う足がかりになれば幸いです。

console.log

javascriptではおなじみコマンドですが、react nativeでもコード内に仕込んでおけば、
アプリを起動しているコンソール上に結果を表示させることが可能です。
開発の初期段階で使う分には手軽に動きを確認できるのでおすすめです。
68b54d05c873d09e61b947cc79c95b2b.gif
ただし、console.logを使ったデバッグは消し忘れの可能性があります。
その上、コードを汚すことになりアンチパターンとされているため実際の開発ではあまり好ましくはありません。

vscode / react native tools

vscodeは本当に優れたEditerで、react nativeのデバッグもプラグイン(React Native Tools)を導入すれば、ブレイクポイントの配置とステップ実行が可能になります。

少し導入に苦戦したので、以下に導入方法を説明します。
※ 以下方法はExpoで開発しているのが前提条件となります。

1. vscodeでReact Native Toolsプラグインをインストール

Extension__React_Native_Tools_—_merchandise_control_system_native_app.png

2. プロジェクトにvscodeのデバッグ設定(launch.json)を追加

ドキュメントには様々な開発パターンの設定が記載されていますが、Expoで開発するのであれば、以下の設定でIOSもAndroidも対応できます。

.vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach to packager",
      "cwd": "${workspaceFolder}",
      "type": "reactnative",
      "request": "attach",
      // Expoのデバッグポートにアタッチ
      "port": "19001"
    }
  ]
}

3. シュミレータIOSもしくはAndroidを起動、デバッグモードをオンにする

シュミレータ上で以下、コマンドを打つことで開発者メニューを開くことができます。

IOSシュミレータ: ctrl + cmd + z
Androidシュミレータ: cmd + m

そのリストの中からDebug Remote JSをクリックします。

508dab625c4ba8eddf989f421951b941.gif

4. vscodeのコードの任意の箇所にブレイクポイントを配置、デバッグ実行

Debug Remote JSをオンにすると、ブラウザでdebugger-ui(http://localhost:19001/debugger-ui/) が開きますが、デバッグポートに対し一つのデバッガしかアタッチできないため、debugger-uiは閉じておきます。(ブラウザのタブを閉じればOKです)

その上でvscode上で先程launch.jsonで作成したデバッガを実行します。
コンソールの画面をDEBUG CONSOLEにすることで、デバッガがアタッチされたか確認することができます。
a6cb0f9dc917c120e65040f5dfdd691d.gif

5. シュミレータを操作し、ブレイクポイントの変数の値を確認

デバッガを実行している状態でシュミレータを操作すると、ブレイクポイントのコードに処理が走ったとき、そこで処理が一時停止します。
その状態で、以下の操作を行うことができます。

  • 変数にカーソルをあてると、変数の内容を確認できる
  • DEBUG CONSOLEで変数の内容を確認したり、さらに処理を一時的を加えることができる
  • ステップ実行して変数の変化を確認
  • 変数をwatchリストに加えて、意図通りに変数が変化するか確認

私が良く活用するのは上記ですが、他にも便利機能があるので、できることの詳細は公式サイトを見たほうがわかりやすいです。

https://code.visualstudio.com/docs/editor/debugging#_debug-actions

b177a9c2e3175e5cc04fbc478beffa6d.gif

react native debugger

react native debuggerは別途アプリをインストールする必要がありますが、「UIのデバック」と「Reduxのデバッグ」を同じアプリ内で行うことができます。
HooksのおかげでReduxの存在感は若干薄まりましたが、それでもなお導入しているプロダクトは多いのではないでしょうか。

react native debuggerダウンロード

以下、リリースページから自分のOSにあうものをダウンロードできます。

https://github.com/jhen0409/react-native-debugger/releases

※ MacであればHomebrewコマンドを打つだけでダウンロードできます。

brew update && brew cask install react-native-debugger

react native debugger初期設定

ダウンロードしたアプリを開き、メニューバー → Debugger → Open Config Fileをクリックします。
.rndebuggerrcファイルが開くので、デフォルトデバッグポートを以下に書き換えます。

// RNDebugger will open debugger window with the ports when app launched
-  defaultRNPackagerPorts: [8080],
+  defaultRNPackagerPorts: [19001],

これで、Expoのデバッガにアタッチできます。
上記vscodeにも記述しましたが、デバッグポートには一つのデバッガしか接続できないためdebugger-uiもしくはReact Native Toolsは閉じておく必要があります。(複数のデバッガを並列実行する方法もあるかもしれませんが、私の調べた限りでは必要に応じて切り替えて使うのが一番簡単かと思います。)

UIデバッグ

シュミレータ上で開発者メニューを開き「Show Element Inspecter」をオンにします。
あとはUIにカーソルを当てると、react native debugger上にUIのstyle・propsなどの状態を確認したり、書き換えたりすることも可能です。リアルタイムで変化を確認できるため大変便利です。

e0cf3ced29f2aeb1370bc329c33a077f.gif

Reduxデバッグ

Reduxのデバッグを行うためには、まずプロダクトコードのstoreファイルに__REDUX_DEVTOOLS_EXTENSION_COMPOSE__の記述をおこないます。

公式サイトにはシンプルな記述方法が記載されています。

https://github.com/zalmoxisus/redux-devtools-extension#11-basic-store

今回のプロダクトではこのような記述にしています。

store.ts
import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';

import { reducer as reduxFormReducer } from 'redux-form';
import itemReducer from '../reducers/item';

import rootSaga from '../sagas/item';

/* eslint-disable no-underscore-dangle, @typescript-eslint/no-explicit-any */
const composeEnhancers =
  process.env.NODE_ENV === 'development' &&
  typeof window === 'object' &&
  (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
    : compose;
/* eslint-enable */

const sagaMiddleWare = createSagaMiddleware();
const enhancer = composeEnhancers(applyMiddleware(sagaMiddleWare));

const store = createStore(
  combineReducers({
    item: itemReducer,
    form: reduxFormReducer,
  }),
  enhancer,
);

sagaMiddleWare.run(rootSaga);

export type AllState = ReturnType<typeof store.getState>;
export default store;

以下はredux-formの例ですが、Redux Actionの発行、Store Stateの変化まで一画面で確認することができます。
それ以外にもアクション名やpayloadの値も確認することができます。

eb4c68e17f00ddce6f8a01ba04d347e7.gif

debugger-ui / chrome dev tools

上記デバッグ手法を使えば、ほぼほぼ開発におけるデバッグは問題ないかと思いますが、debugger-uiChrome dev toolsを使ったデバッグも可能です。
ff88f4524f38b9a53f4a8d4487ae55db.png

ただし、この手法は以下の理由から、今回の開発では使いませんでした。

  • Expoの公式Debuggingドキュメント「Source maps and async functions」内でchrome dev tools内のsource mapと非同期関数は100%信用できないとの記述があること。(であれば、vscodeでステップ実行したほうが良い?)
  • TypescriptWebpackの設定の影響か、うまくsource mapがうまく生成されなかった

Typescript・Webpackなどの設定を見直せばうまくデバッグできるようになるかもしれませんが、Expoを利用した開発では「vscode」と「react native debugger」で十分デバッグ機能は果たしていると考え、今回はあまり深く追求せず進めることにしました。
もし、このデバッグ手法にメリットを発見する、もしくはもっと簡単にデバッグができる方法を見つけたら記事を更新したいと思います。

49
53
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
49
53

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?