はじめに
最近ハッカソンに参加した際に採用したフロントの技術が個人的にかなりしっくりきたので紹介したいと思います. 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
ディレクトリ配下にcomponents
と store
というディレクトリを作成します.
これで前準備は完了です.
実装
今回はGitHubのユーザー名を指定して,そのユーザー名のリポジトリ一覧を取得する簡単なアプリケーションを実装していきます.
はじめに,unstatedを用いたstoreについての実装から行います.こちらは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を実装します.コードは以下のようになります.
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.tsx
とindex.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;
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の開発を行なっていこうと思います.