ReactでTypeScriptってどうやって書いていくのだろう
本記事では、どのようにReactでTypeScriptを用いたプロジェクトを作成するのか、またどのように型定義をしていくのかを簡単に解説しています。
また、本記事は、Raise Techのフロントエンドエンジニアコースの受講記でもあります。
こちらの記事は、第9回の講義のまとめとなります。
僕もまだ勉強中なので間違っている認識があるかもです。
気づいたら教えてもらえるとうれしい。。
まずは、TypeScriptのプロジェクトファイルを作ってみる
ということで、さっそくTypeScriptのプロジェクトファイルを作ってみます。
作り方は非常に簡単でコマンドを打つだけでいけます。
まずは、ターミナルを開いてプロジェクトを作りたいディレクトリに移動します。
npx create-react-app 好きな名前 --template typescript
作られたフォルダをエディタで開きます。中に入っているファイルを見てみましょう。
ファイルの拡張子が、jsx
ではなくtsx
になっているのが分かるかと思います。
これがTypeScript用のファイル拡張子になります。
一旦これで、プロジェクトファイルを作ることができました。
Reactのとき同様、npm start
をコマンドで叩けばブラウザが立ち上がりお馴染み?の画面が表示されます。
めっちゃ簡単、、、!!
ESLintとPrettierの設定
ここは、めっちゃ長くなりそうなので設定済みのファイルのGitリポジトリと参考になった記事を貼っておきます。
▼Gitリポジトリ
https://github.com/takahiro-okada/typescript-default
▼ESLintの設定
▼Prittierの設定
▼VSCodeの設定
StateやPropsの型定義
では、RaiseTechのフロントエンドコースの第10回で教えてもらったことを使いながらReact開発ではどのように型定義をしていくのかをみていきましょうー
Stateの型定義
まずは、useState
での型定義の方法について。
useState
で型定義をするには、ジェネリクスで型を定義します。
const [text, setText] = useState<string>("");
return (
<div className="App">
<h1>value:{text}</h1>
<input
type="text"
value={text}
onChange={(e) => setText(e.target.value)}
/>
</div>
1行目のconst [text, setText] = useState<string>("");
と記述することで、text
に入ってくる値はstring型
と定義することができます。
間違った値(例:number型)を入れるとエラーを出してくれます。
Propsの型定義
フォルダ構成です。App.tsx
でPage.tsx
を呼ば出す形にして、その際にProps
を渡したいと思います。
export default function App() {
const greetJapanese = () => {
alert("こんにちは!!!!!");
};
const greetEnglish = () => {
alert("Hello World");
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Page name={"オカ"} age={31} greeting={greetJapanese} />
<Page age={20} greeting={greetEnglish} />
</div>
);
}
type Props = {
name?: string;
age: number;
greeting: () => void;
};
export const Page = (props: Props) => {
const { name = "山田太郎", age, greeting } = props;
return (
<>
<p>名前:{name}</p>
<p>年齢:{age}</p>
<button onClick={greeting}>挨拶する</button>
</>
);
};
Page.tsx
で受け取る型の定義をしています。
type Props = {
name?: string;
age: number;
greeting: () => void;
};
name?: string;
の?
はオプショナルといって、必ずしも渡す必要のないPropsにつけることで渡ってこなくてもエラーがでないようにすることができます。
const { name = "山田太郎", age, greeting } = props;
では分割代入をしており、もしname
が渡ってこなかったときにはデフォルトで山田太郎
が渡されるようになっております。
実際の動くコードになります。
型定義用のファイルを作る
React
では共通の部分に関しては、コンポーネント化して使い回しができるようにしてきました。
TypeScript
においても型定義の部分をコンポーネント化して複数のところで使い回せるようにするといいようです。
今回課題でメモアプリを作った際に、上記のように取得してくるメモの型を定義して、複数箇所で使えるようにしました。
取得データへの型定義
axios
などでAPIから外部のデータを取得してくるときに型情報がないので自分で型を定義して指定する必要があります。
いくつか記述方法がありますが、一番オススメされていたのは、axiosのジェネリクスで指定するパターンです。
import axios from 'axios';
const axiosInstance = axios.creat({
baseURL:'https://jsonplaceholder.typicode.com/',
});
type User = {
id: number;
name:string;
username: string;
email :string;
};
export const fetch = async () => {
try {
const result = await axiosInstance.get<User>('/users');
return result.data;
} catch (error) {
alert('通信に失敗しました');
}
};
このように記述をすることで取得するdata
はUser型
となります。
コンポーネント自体への型定義
関数コンポーネントそのものに型定義をすることができます。
型定義をしておくことで、コンポーネントのプロパティが補完されるなど安全にコンポーネントを扱えるようになります。
使える方はFC型とVFC型となります。
▼FC型
型定義に暗黙的にchildrenを含んでいる。
▼VFC型
型定義にchildrenは含んでおらず、明示的にchildrenを型定義する必要がある。
※バージョン18からはFC型からもchildrenが除外されるようです。
VFC型でchildren
を指定しないと怒られます。(上記画像)
これで関数コンポーネントにchildren
が含まれているかどうかがわかるようになりました!
前回作ったToDoアプリをTypeScriptに書き換えてみる。
一度Reactで作成したToDoアプリをTypeScriptに書き換えながらTypeScriptの勉強をしていきます。
まだ作成途中ですが、こちらにGithubにあげているソースコードを公開しておりますのでよかったら見てみてください。
まとめ
TypeScriptがわかるようになると特に保守・運用フェーズで非常に便利みたいなのでしっかり身につけていきたいと思います。
正直今は、型を考える余裕がないレベルなので、、、。
楽しみながらコツコツ毎日やっていきますー。`