5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【5分でわかる】React + TypeScript + unstated

Posted at

はじめに

最近ハッカソンに参加した際に採用したフロントの技術が個人的にかなりしっくりきたので紹介したいと思います. GitHubのリポジトリ一覧を取得するAPIを用いて説明を行います.

【!注意!】 本記事はReactの記法やunstatedの使い方について詳しく説明を行う記事ではなく,あくまでこうした技術を用いてコーディングするとやりやすかったですというのを紹介する記事となっています.

プロジェクト作成

今回はcreate-react-appを用いてプロジェクト作成を行います.create-react-appを用いる場合,オプションをつけるだけで簡単にTypeScriptバージョンのプロジェクトを作成できます.

> create-react-app --scripts-version=react-scripts-ts {プロジェクト名}

次に unstated の導入を行います.また,API通信を行うときに用いるaxios も同時に導入しておきます.

> yarn add unstated
> yarn add axios @types/axios

続いて,作成したプロジェクトのディレクトリの中のsrcディレクトリ配下にcomponentsstore というディレクトリを作成します.

これで前準備は完了です.

実装

今回はGitHubのユーザー名を指定して,そのユーザー名のリポジトリ一覧を取得する簡単なアプリケーションを実装していきます.

はじめに,unstatedを用いたstoreについての実装から行います.こちらはstore/githubContainer.tsxとして実装を行なっていきます.
コードは以下のようになります.

store/githubContainer.tsx

import { Container } from "unstated";
import axios from "axios";

interface Repository {
  name: string;
}

interface GitHubState {
  userName: string;
  repositories: Repository[];
  err: string;
}

export class GitHubContainer extends Container<GitHubState> {
  constructor() {
    super();
    this.state = {
      userName: "",
      repositories: [],
      err: ""
    };
  }

  setUserName(input: string) {
    this.setState({ userName: input });
  }

  fetch(userName: string) {
    axios
      .get("https://api.github.com/users/" + userName + "/repos")
      .then(res => {
        this.setState({ repositories: res.data });
      })
      .then(err => {
        console.log(err);
        this.setState({ err: "Fetch Repository Error" });
      });
  }
}

unstatedが本来Viewファイル(今回でいうとcomponents/に入るようなファイル)に入るところのstateを別ファイルに切り出してくれているという風に考えるとわかりやすいかと思います.今回はGitHubのリポジトリを取得するので, Repository というinterfceを作成してそのリストをstateに持たせるようにしました.こうした実装ができるところがTypeScriptのいいところで,JSに比べてかなり可読性が高く直感的なコードが実現できています.

次にcomponents/repositories.tsx にViewを実装します.コードは以下のようになります.

components/repositories.tsx
import * as React from "react";
import { Subscribe } from "unstated";
import { GitHubContainer } from "../store/githubContainer";

interface RepositoriesProps {
  container: GitHubContainer;
}

export class RepositoriesContainer extends React.Component<
  RepositoriesProps,
  {}
> {
  constructor(props: RepositoriesProps) {
    super(props);
  }

  render() {
    return (
      <div>
        <div>
          <input
            placeholder="Input GitHub User Name..."
            onChange={e => this.props.container.setUserName(e.target.value)}
          />
          <button
            onClick={() =>
              this.props.container.fetch(this.props.container.state.userName)
            }
          >
            GET!
          </button>
        </div>
        <ul>
          {this.props.container.state.repositories.map(repository => (
            <p> {repository.name} </p>
          ))}
        </ul>
      </div>
    );
  }
}

const RepositoriesWrapper = () => (
  <Subscribe to={[GitHubContainer]}>
    {(container: GitHubContainer) => (
      <RepositoriesContainer container={container} />
    )}
  </Subscribe>
);

export default RepositoriesWrapper;

ここで肝となっているのは, RepositoriesWrapper の部分で,本来unstatedのstoreを用いるには少々面倒な書き方を行う必要があるのですが(unstated公式ページ参照),そのstoreをあらかじめpropsに設定しておくことでどこからでも簡単に呼び出すことを可能にしている点です.こうすることでstoreを簡単に用いることができるだけではなくunstatedを普通に用いた場合のなんとも言えぬゴチャゴチャ感を感じずに実装を行うことができます.
ここら辺の技術はこの記事を参考にさせていただきました.

あとはApp.tsxindex.tsxに修正を加えてアプリが動作するようにします.

App.tsx
import * as React from "react";
import "./App.css";
import RepositoriesWrapper from "./components/repositories";

class App extends React.Component {
  public render() {
    return (
      <div className="App">
        <RepositoriesWrapper />
      </div>
    );
  }
}

export default App;
index.tsx
import * as React from "react";
import * as ReactDOM from "react-dom";
import App from "./App";
import { Provider } from "unstated";
import "./index.css";

ReactDOM.render(
  <Provider>
    <App />
  </Provider>,
  document.getElementById("root") as HTMLElement
);

最後にアプリを実行して,きちんと動作するか確認してみてください.

さいごに

今までJSを用いてReactでの開発を行なっていたのですが,今回の技術セットを用いた開発がかなり良いと感じたので紹介しました.よほど大規模なプロジェクトでない場合,しばらくはこの技術セットを用いてReactの開発を行なっていこうと思います.

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?