2021/08/05

React + TypeScriptを勉強する

@ 酒井悠宇

ReactのどこでTypeScriptの型定義を行うかがいまいちよくわからないので、その辺を理解するために記事書きます!

まずは以下のコマンドでcreate-react-appのtypescriptプロジェクトを作成。

create-react-app my-app --template typescript

axiosをインストール。これはwebAPIを簡単に呼び出すことができるようになるライブラリ。超シンプルなのでいい感じ。

npm install axios

tsconfig.jsonのstrictをfalseにしておきます。これをすると型定義しなくてもコンパルエラーが出ません。
型定義のありがたみをわかりやすくするためにfalseにしておきます。

"strict": false

axiosを使用したデータの取得

データを簡単な構文でfetchできるaxiosというライブラリを使用して、jsonplaceholder(テストとかに使えるjson形式のデーターがたくさん集まっている場所)からデータをとってきながら、実際にReact + TypeScriptで型定義を行ってみたいと思います。

まずはApp.tsx内にてaxiosをインポート。

//App.tsx
import { axios } from 'axios'

コンポーネント内に実際にデータをとってくる関数を定義します。
axiosは、「axios.(行いたいhttpリクエスト).then(処理が終了した後に行いたい処理)」みたいに超シンプルな構文でデータを持ってきて、処理を行うことができます。
今回はjsonplaceholderからtodosというデータを持ってきたいと思います。

実際の中身はこんな感じです。実際には200件程入っています。

配列の中にオブジェクト形式でtodoのデータが入っています。

このデータのurlをgetの引数に渡してそれをログに出力するという関数を定義します。

  const onClickFetchData = () =>  {
    axios
    .get("https://jsonplaceholder.typicode.com/todos")
    .then((res) => {
      console.log(res);      
    })
  }


コンポーネントのjsx内に先程の関数を呼び出す処理を記述します。

export default function App() {

  const onClickFetchData = () =>  {
    axios
    .get("https://jsonplaceholder.typicode.com/todos")
    .then((res) => {
      console.log(res);      
    })
  }
  return (
    <div className="App">
      <button onClick={onClickFetchData}>データ取得</button>
    </div>
  );
}

「データを取得」というボタンを押すと、関数内に定義したaxiosがjsonplaceholderからtodoのデータをとってきてくれる仕組みです。
実際にやってみましょう。

データが返ってきました。さまざまな項目がありますが、axiosではdataという項目の中に実際にとってきたデータが格納されているようです。


きちんと入ってました。


次は実践的に、axiosでとってきたtodosのデータをstateに保持して、それを一覧表示する機能を実装してみます。

useStateをimportして

import { useState } from 'react';


stateを定義

const [todos, setTodos] = useState([]);


とってきたデータをsetStateします。

  const onClickFetchData = () =>  {
    axios
    .get("https://jsonplaceholder.typicode.com/todos")
    .then((res) => {
      setTodos(res.data);
    })
  }


stateに入ったデータをmapで回して表示します。

  return (
    <div className="App">
      <button onClick={onClickFetchData}>データ取得</button>
      {todos.map((todo) => (
        <p>{todo.title}</p>
      ))}
    </div>
  );


「データを取得」というボタンを押すと、axiosがとってきたデータをsetStateする関数が動いて、その関数に入ったデータがmapで回されてビューに表示される仕組みです。
実際にやってみましょう。

いい感じにとってこれました。実際には200件表示されています。

いざ型定義

それでは実際にTypsScriptで型定義を行っていきます。

取得してきたデータの型定義

今回jsonplaceholderから持ってきたデータは、配列の中にそれぞれオブジェクト形式で格納されています。
なので、オブジェクトの型を定義する必要があります。
オブジェクトの型を定義するには、interfaceを使う方法とtypeを使う方法がありますが、今回はtypeを使用してオブジェクトの型を定義していきます。

jsonplaceholderのtodosに格納されているデータを実際に見てみます。

  {
    "userId": 1,
    "id": 1,
    "title": "delectus aut autem",
    "completed": false
  },

数字や文字列、真偽値が格納されてありました。

このオブジェクトの型をtypeで定義するとこんな感じになります。

type TodoType = {
  userid: number;
  id: number;
  title: string;
  completed: boolean;
}

これでTodoTypeという名前のオブジェクトの型を定義することができました。

この型を実際にaxiosで持ってきたデータに当てはめてみるとこんな感じになります。
todosのデータは配列の中にオブジェクト形式で格納されているので、<Array<TodoType>>のような書き方になります。

  const onClickFetchData = () =>  {
    axios
    .get<Array<TodoType>>("https://jsonplaceholder.typicode.com/todos")
    .then((res) => {
      setTodos(res.data);
    })
  }


このように型定義を行うことで、vscodeが格納されているデータを予測で出してくれるようになります。

これは開発の効率が上がりそうですね。

stateの型定義

axiosで持ってきたデータをセットするstateにも型を定義してみましょう。

const [todos, setTodos] = useState<Array<TodoType>>([]);


このようにすることで、todosに型に当てはまらない値をsetState使用しようとするとコンパイルエラーになったり


タイポを指摘してくれたりします。userId のはずが userid になっている。

安全性が爆あがりですね。

propsの型定義

今回はjsonplaceholderの中のcompletedがtrueなら[完]の文字を、falseなら[未]の文字を表示させるという機能を実装するとします。


完成形はこんな感じです。


では実際にpropsに型定義を行っていきましょう。
今回は、userid, title, completedをオブジェクト形式でpropsで受け取りたいので、typeを使って以下のような型を定義します。

type TodoType = {
    userId: number;
    title: string;
    completed: boolean;
}


これを実際にpropsに当てはめてみます。
早速タイポを指摘してくれています。


コンポーネントにに渡すpropsが足りていない場合それも指摘してくれます。

TypeScript最高!

キーの最後に?をつけることで、その値は必須ではないということを宣言できます。

type TodoType = {
    userId: number;
    title: string;
    completed?: boolean; //必須ではないことを表す
}


必須ではないので、送られてこない場合のことを考えてデフォルト値を設定しておくといい感じです。

const { title, userId, completed = false } = props;


今回は取得してきたデータの型定義と、stateの型定義と、propsの型定義についてまとめました。!
今後は型定義を効率的に行う方法や、コンポーネント自体の型定義についてもまとめていきたいです!
最後までごらんいただきありがとうございました!

© 2021 powerd by UnReact