Reactの続きです。前回はstyled-componentsのcss helperでスタイルを継承し、CSS設定を完成させました。今回はTypeScript編。以前メタ言語スターターキットで作ったTypeScriptのモジュールをReact環境に追加してみます。処理の対象はReactの仮想DOMです。それではいきましょう!
【目次】
- 前回のおさらい
- 「hello.js」の処理内容
- 「hello.js」を「hello.ts」に変更
- 「message.ts」を作成
- 「hello.json」を作成
- 「data.json」のclass名も.helloに変更
- Innerコンポーネントのインポート部分を修正
- ブラウザ確認
- 最後に
※参考:前回記事
【React】styled-componentsのcss helperでスタイルを継承(Reactとメタ言語の比較-5) - クモのようにコツコツと
※参考:Reactを習得するためにやったことまとめ
qiita.com
前回のおさらい
CSS設定を復活させる。styled-componentsのcss helperを使い共通スタイルを継承できた。 JSXコンポーネントと同じファイルにCSS in JSでスタイルを書いてるのでEJS + Sass(SCSS)と比べてファイル数は半分になった。
また、ランダムなclass名が作られてスコープになるため、BEMのclass名は不要になった。 CSS設定は別ファイルではなくheadタグの中にあるようだ。
※参考:【React】styled-componentsのcss helperでスタイルを継承(Reactとメタ言語の比較-5) - クモのようにコツコツと
「hello.js」の処理内容
現在、「modules/hello」フォルダの中にある「hello.js」というピュアなJSファイルを実行している。
「hello.js」の内容
const hello = JSON.parse( '{"message":{"text":"こんにちは、ふろんとえんど。","selector":".inner__text--hello"}}' ); const message = { text: hello.message.text, selector: hello.message.selector }; const text = message.text; const selector = message.selector; document.addEventListener("DOMContentLoaded", () => { document.querySelector(selector).innerHTML = text; console.log("text-> " + text); });
これはメタ言語スターターキットでTypeScript→JSコンパイル後のコードがベースになっている。
※参考:【メタ言語】フロントエンド開発スターターキットを作った(EJS、Sass(SCSS)、TypeScript) - クモのようにコツコツと
この処理をコンパイル前のTypeScriptモジュールの状態に再現してみる。
「hello.js」を「hello.ts」に変更
「hello.js」のファイル名を「hello.ts」に変更する。
import { message } from './message'; const text: string = message.text; const selector: string = message.selector; const hello = (): void => { document.addEventListener('DOMContentLoaded', () => { const dom: HTMLButtonElement = document.querySelector(selector) as HTMLButtonElement; dom.innerHTML = text; console.log('text-> ' + text); }); } export { hello };
message
モジュールをインポートしてhello
関数をエクスポートする。
message
モジュールからtext
を読み込んでselector
のDOMに表示する、という内容。
なお、拡張子は前回の「mixin.ts」と同様、JSXを含むファイルとロジックのみのファイルを明確にするため、「.ts」で統一することにする。
※参考:TypeScript - Reactを使うプロジェクト内のTypeScriptをすべて.tsxで作るデメリットについて|teratail
「message.ts」を作成
同じフォルダに「message.ts」を作成する。
import hello from '../../data/hello.json'; const message: {[key: string]: string;} = { text: hello.message.text, selector: hello.message.selector }; export { message };
「hello.json」をインポートして、message
関数をエクスポート
このモジュールではhello.json
から読み込んだデータをstring型付きの連想配列にしている(jsonデータはそのままだとany型になるため)。
「hello.json」を作成
次に「data」フォルダに「hello.json」作成する。
「hello.json」の内容
{ "message": { "text": "こんにちは、りあくと。", "selector": ".hello" } }
text
キーは「こんにちは、りあくと。」、selector
キーは.hello
。
「data」フォルダはページに表示しているテキストデータ「data.json」を入れていたフォルダ。
text
キーはメタ言語スターターキットの時は「こんにちは、ふろんとえんど。」だったが「こんにちは、りあくと。」に変更してみた。
selector
キーのclass名はの時はBEM記法の.inner__text--hello
だったが、この環境ではBEM記法にする必要がなくなったので.hello
と短くしてみた。
※参考:【メタ言語】フロントエンド開発スターターキットを作った(EJS、Sass(SCSS)、TypeScript) - クモのようにコツコツと
「data.json」のclass名も.hello
に変更
「hello.json」と同じ「data」フォルダにある「data.json」を修正
"inner": [ // 中略 { "title":"JS(文字列)", "text": "JSでテキストの文字列追加「<span class='hello'></span>」" } ],
ここのtext
キーにもBEM記法のclass名.inner__text--hello
があったが.hello
に変更した。
Innerコンポーネントのインポート部分を修正
hello
モジュールをインポートしているInnerコンポーネント(Inner.tsx)のインポート部分を修正する。
修正前(「hello.js」をインポート)
import './modules/hello/hello';
JSファイルをインポートする時はこれだけで済んだ。
修正後(「hello.ts」のhelloモジュールをインポート)
import { hello } from './modules/hello/hello';
TSファイル「hello.ts」でexport
しているhello
関数を指定してインポートする。
そしてインポートしたhello
モジュールの関数を実行する。
// modules
hello();
この処理はメタ言語スターターキットのTypeScriptモジュールに準ずる。
※参考:【メタ言語】フロントエンド開発スターターキットを作った(EJS、Sass(SCSS)、TypeScript) - クモのようにコツコツと
ブラウザ確認
アプリをローカルで起動
$ npm start
おお、メッセージ「こんにちは、ふろんとえんど」が「こんにちは、りあくと。」になった!
タグのclass名も.hello
に!
元のソールは#root
しかない。.hello
はReactでレンダリングされた仮想DOM
ピュアなTypeScriptモジュールの処理がReactの仮想DOMにも適用されることがわかった!
ソース(GitHub)
※参考:GitHub - ryo-i/react-from-meta-lang
プレビュー(GitHub Pages)
※参考:Reactとメタ言語の比較
最後に
ということで、メタ言語スターターキットのTypeScriptモジュールをほぼそのままの形で追加し、問題なく動くことがわかりました!(しかも処理の対象がReactの仮想DOM)
本環境は元々React + TypeScript環境でしたが、TypeScriptは型を付けないピュアなJSも普通に動くので、これまであまり型を意識せずにコードを書いていました(たまに型推論でエラーを教えてくれる程度)。
今回、型付きTypeScriptモジュールを追加し、問題なく動いたのでReact環境でTypeScriptモジュールは両立可能とわかりました。これからはReact処理の中にもTypeScriptの型指定などの記述を加えていきたいと思います。
また、ファイルが増えるとJSXコンポーネントとそれ以外の処理ファイルがわかりにくくなってくるのでファイル名を下記で統一していこうと思います。(React機能上は全部「.tsx」、または全部「.ts」でも問題ないようです)
- JSXコンポーネントは1文字目大文字で拡張子は「.tsx」
- それ以外のファイルは小文字で拡張子は「.ts」
メタ言語スターターキットをReact環境に移行するシリーズは今回で終了になります。メタ言語スターターキットでやれていたモジュール分割などはReactでも実現可能とわかりました。また、モジュールがコンポーネントごとに一体化できてファイル数が少なく済むのメリットも感じました。
次回からはまた別のことに取り組んでいきます。それではまた!
※参考:Reactを習得するためにやったことまとめ
qiita.com