概要
前回記事で書いた「りあクト!」を読んで学んだことですが、現在のReactでは関数コンポーネントが主流になっており、公式チュートリアルでメインに扱われているクラスコンポーネントはあまり用いられないようです。 また、実践的な開発では、JavaScriptよりもTypeScriptが主に使われています。
そこで、ReactチュートリアルをTypeScript、関数コンポーネント、Hooksで書き直してみました。 流れは公式チュートリアルのままになっています。
※とはいえ、stateを理解するにはクラスコンポーネントを理解しておくと良さそうなので、いきなりHooksを使うより、一度公式チュートリアルをやってよかったかなと思います。
私がトライしたときに作ったコードはこちらです↓
主な環境
- macOS 11.4
- node 14.4.0
- TypeScript 4.3.2
- React 17.0.2
チュートリアルの準備
基本的にはこの公式チュートリアルの流れに従って準備します。
手順
npx create-react-app my-app --template=typescript
でプロジェクトを作成- 作成された
my-app/src/
配下のファイルを全部消す src
配下に、index.tsx
を作成し、このコードをコピペ- 同じく
index.css
を作成し、このコードをコピペ
スターターコードの中身
このindex.tsx
は、公式チュートリアルのスターターコードindex.js
を関数コンポーネントとTSで書き直したものです。
import { VFC } from 'react'; import ReactDOM from 'react-dom'; import './index.css'; const Square: VFC = () => ( <button type="button" className="square"> {/* TODO */} </button> ); const Board: VFC = () => { const renderSquare: VFC = () => <Square />; const status = 'Next player: X'; return ( <div> <div className="status">{status}</div> <div className="board-row"> {renderSquare(0)} {renderSquare(1)} {renderSquare(2)} </div> <div className="board-row"> {renderSquare(3)} {renderSquare(4)} {renderSquare(5)} </div> <div className="board-row"> {renderSquare(6)} {renderSquare(7)} {renderSquare(8)} </div> </div> ); }; const Game: VFC = () => ( <div className="game"> <div className="game-board"> <Board /> </div> <div className="game-info"> <div>{/* status */}</div> <ol>{/* TODO */}</ol> </div> </div> ); // ======================================== ReactDOM.render(<Game />, document.getElementById('root'));
各関数コンポーネントにくっついてるVFC
は、関数コンポーネントの型を表します。
具体的にはprops
を引数にとり、ReactElement
もしくはnull
を返す関数として定義されているオブジェクトです。
VoidFunctionComponent
のエイリアスになっていて、VFC
と表現できます。
参考
(Reactの関数コンポーネントの型には、元々FunctionComponent
型があったようですが、現在推奨されていないようです。「りあクト!」にも同様の説明がありました。こちらの記事がわかりやすかったです)
個人的に気になったこと
JS/TSには関数閉包(クロージャ)という概念が存在し、関数の中に関数を定義することができます。 (正確には、関数の中に関数を定義できるから、関数閉包ができると言ったほうがいいかもしれません)
C++やPythonを主に扱ってきた私としては、なかなか奇妙な感じがします。
このコードでも、次の箇所に使っています。
const Board: VFC = () => { const renderSquare: VFC = () => <Square />; ︙
関数閉包については、こちらのページがわかりやすかったです。
余計な説明が多くなりましたが、次回からこのコードをチュートリアルに従って三目並べを作っていきます!