この記事は、Zennにも投稿しています。
この記事でやること
- React Native for Windows(以下 RN4W)のプロジェクトを作成してそこに C++を使って Windows ネイティブの機能を追加します。
- 今回はサンプルとしてボタンがクリックされた時にイベントが発火するようなものを作っていきます。
前提
こちらに書いてある通りなのですが一応書いておくと
- nodejs
- Visual Studio 2019
- Universal Windows Platform development
- Desktop development with C++
またそれに加えてこの記事では
- VSCode
- VSCode の React Native Tools 拡張機能
も使うのでこれらをインストールしておいてください。
1. プロジェクトを作成
それではこちらに従って新しいプロジェクトを作成していきます。
新しい React Native のプロジェクトを作ります。今回は TypeScript を使います。
RN4W を入れます。
2. VSCode を設定して React Native パッケージャとデバッガを起動
VSCode に React Native Tools を入れて起動設定を作るだけで JS 側はほぼ設定いらずでデバッグ等ができてとても便利です。
- まず VSCode で
rn4wSampleApp
のフォルダを開きます。 .vscode/launch.json
を作成し以下のように書き換えてください。
これで VSCode 左部からデバッグができるようになります。
すると VSCode がアタッチ待ちの状態になり、React Native パッケージャーが起動するのでそのまま次に進んでください。
Launch UWP
を選んで実行すれば起動するのですが今回はそれではなくAttach
を選択して実行しておいてください。すると VSCode がアタッチ待ちの状態になり、React Native パッケージャーが起動するのでそのまま次に進んでください。
3. アプリを起動
windows/rn4wSampleApp.sln
を Visual Studio で開きます。- 上部のコンボボックスから
x86
かx64
を選び実行します。初回は結構時間がかかるので気長に待ちます。 - ウインドウが表示され、先ほど起動しておいた VSCode のデバッガにアタッチされるはずです。その後しばらく待ち、「Welcome to React」の画面が表示されたら成功です。
4. ネイティブコードを書く
ここまでの手順だけでも普通に RN4W を使うことができますが、やはりネイティブ機能を使いたいときが出てくるでしょう。RN4W では UWP の機能を呼び出すことができます。その機能を使って今回はマウスボタンがクリックされたときにイベントを JS 側に送るようにしたいと思います。
- Visual Studio でソリューション内にある
rn4wSampleApp
プロジェクトを右クリックし、「追加」->「新しい項目」と選択します。 - 出てきた画面で「ヘッダーファイル (.h)」を選択し、ここでは「MouseHandler.h」と名づけることにしてファイルを新規作成します。
rn4wSampleApp
内にあるReactPackageProvider.cpp
に今作ったファイルを include させます。include の末尾に次の行を加えてください。MouseHandler.h
を編集します。以下のように書き換えてください。実行してエラーが出なければ成功です。
簡単に解説します。といってもこちらにある通りなのですが、マクロが用意されていて、それを使うことでうまい具合に関数を JS 側から実行させたりできます。
まず
今回は
また基本的に C++でつけた名前がそのまま JS でも使われますがマクロの第二引数に文字列を入れると JS 側から別名で呼び出せたりします。
まず
REACT_MODULE
でモジュールを指定します。そして指定した構造体の中にいろいろ書いていきます。今回は
REACT_METHOD
とREACT_EVENT
を使っていますが、REACT_METHOD
は関数を JS から実行できるものでREACT_EVENT
は JS 側で登録しで JS 側のイベントを発火させることができます。また基本的に C++でつけた名前がそのまま JS でも使われますがマクロの第二引数に文字列を入れると JS 側から別名で呼び出せたりします。
5. JS 側から実行する
さて、このままではうまくいってるんだかわからないので今度は JS 側のコードを書き換えていきます。
App.tsx
を次のように書き換えます。このコードを見たら大体わかっていただけると思いますが
というか NativeModules の下は any になってるので TypeScript にした意味あんまりありませんでしたね・・・
実際に使うときはちゃんと型定義を書いた方が良いでしょう。
NativeModules.上のREACT_MODULEで指定した名前.REACT_METHODで指定した名前
の形でネイティブの関数を呼び出すことができます。そして NativeEventEmitter のインスタンスを作り addListener の第一引数にREACT_EVENTで指定した名前
を入れることでネイティブからのイベントを実行することができるようになります。というか NativeModules の下は any になってるので TypeScript にした意味あんまりありませんでしたね・・・
実際に使うときはちゃんと型定義を書いた方が良いでしょう。
さて、コードを保存したらアプリ上で
アプリ上でなにかマウスのボタンをクリックするととても地味ですが表示が切り替わるはずです!
Ctrl+Shift+D
を押して「Reload Javascript」を選択してください。アプリ上でなにかマウスのボタンをクリックするととても地味ですが表示が切り替わるはずです!
感想
- React Native よりも UWP の情報を調べるのと自分が普段 Web 系の言語しか書いてないのもあって C++を書くのにも苦労しました。C++の説明で頓珍漢なこと言ってたら申し訳ないです。
- 一番きつかったのは UWP の API を調べることでした。最初はどのマウスボタンが押されたのか判別する API を見つけられなくてあきらめかけていました。公式のドキュメントを見ながら頑張りましょう。
- C++については調べても C++/CX という似て非なるもののコードが載ってたりしてコピペしても動かなかったりしてつらかったのとそもそも C++で UWP を使うコード例がほとんど見当たりませんでした。C#では普通にプロパティでアクセスしているものが C++だと関数になっていたりとかいろいろつらかったです。
その他
- 一応 C#で作ることも可能なようなのですがうまくいきませんでした。RN4W が C#で作られていたころはうまくいったのかも・・・?
- UWP アプリ以外は作ることができません。ただこれから WinUI3 をサポートして古いバージョンの Win10 もサポートするみたいなことが書いてあったので将来的には他の形式にもできるかもしれません。
- 最初に init 関数を呼ばないと動かないのはどうなのかと思ったのですがこれしか方法が見つけられませんでした・・・
参考にしたサイト
Native Modules · React Native for Windows + macOS
> **This documentation and the underlying platform code is a work in progress.**
microsoft.github.io
RN4W の公式ドキュメントです。わかんないことがあればここを見るのがベスト。
Windows UWP 名前空間 - Windows UWP applications
docs.microsoft.com
UWP の公式ドキュメントです。ここを見るのがいいというかここにしか情報がないです。
Building a React Native module for Windows
In this blog post we're going to learn how we can build such a native module with Windows support, so that we can access to native Windows APIs when our..
techcommunity.microsoft.com
C#で作る記事です。上に書いた通り自分はうまくいかなかったのですがもしかしたらうまくいくのかもしれません。