Posted at

create-react-appを使ったTypeScriptのチュートリアル

Reactにまだ慣れていない、TypeScriptを今からはじめて触れる人向けに、簡単なチュートリアルを書きます。

この記事の他にもTypeScriptのチュートリアル記事はいくつかありますので、そちらも参考にどうぞ

TypeScriptチュートリアル① -環境構築編-

TypeScript チュートリアル

今回はReduxや、Sagaなどのミドルウェアは一切使わずにとてもシンプルなアプリケーションを作ります。


環境構築

create-react-appを使えばReactの環境構築は簡単にできます。

https://github.com/facebook/create-react-app

今回はTypeScriptを使うので下記のようにコマンドを入力します

npx create-react-app sample-app --typescript

上のコマンドのsample-appの部分がフォルダ名になります。

create-react-appで作成したフォルダに移動してアプリケーションを起動します

cd sample-app/

npm start

これでとりあえず初期画面が表示されました。簡単。

スクリーンショット 2019-07-19 15.53.45.png


コンポーネントを編集してみる

最初に表示されている画面のコードはsrc/App.tsxに記載されています。


App.tsx

import React from "react";

import logo from "./logo.svg";
import "./App.css";

const App: React.FC = () => {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
};

export default App;


Reactの開発は基本的にsrcフォルダ内に書いていきます。

まずはこのApp.tsxをもっとシンプルなものに書き換えます。


App.tsx

import React from "react";

class App extends React.Component {
render() {
return <p>Hello world</p>;
}
}

export default App;


スクリーンショット 2019-07-19 16.11.47.png

Hello worldが表示されるだけのシンプルな画面になりました。

別のコンポーネントを作成してApp.tsxにimportしてみます。


Sample.tsx

import React from "react";

class Sample extends React.Component {
render() {
return <p>2つ目のコンポーネント</p>;
}
}

export default Sample;



App.tsx

import React from "react";

import Sample from './Sample'

class App extends React.Component {
render() {
return (
<p>Hello world</p>
<Sample/>
);
}
}

export default App;


これで立ち上げてみます。

Failed to compile.

./src/App.tsx
Line 9: Parsing error: JSX expressions must have one parent element

エラーになりますね。

エラー内容の通り、jsxでは一つの親要素が必要となります。

<React.Fragment>で全ての要素を囲むことでこのエラーを回避できます。


App.tsx

import React from "react";

import Sample from "./Sample";

class App extends React.Component {
render() {
return (
<React.Fragment>
<p>Hello world</p>
<Sample />
</React.Fragment>
);
}
}

export default App;


これで問題なく画面が表示されました。

スクリーンショット 2019-07-19 16.22.18.png


Propsを使ってみる

ReactにはPropsとStateという2つの変数が存在します。

ふたつの変数の違いについてはこちらの記事をどうぞ。

React における State と Props の違い

今からはじめるReact.js〜propsとstate、それからrefs〜

先程作成したSample.tsxにApp.tsxから変数を渡してみましょう。


App.tsx

import React from "react";

import Sample from "./Sample";

class App extends React.Component {
render() {
return (
<React.Fragment>
<p>Hello world</p>
<Sample num={"5"} />
</React.Fragment>
);
}
}

export default App;


ここではnumという変数に"5"という文字列を代入しています。


Sample.tsx

import React from "react";

class Sample extends React.Component {
render() {
return <p>{this.props.num}つ目のコンポーネント</p>;
}
}

export default Sample;


またエラーになりました。

Type '{ num: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Sample> & Readonly<{}> & Readonly<{ children?: ReactNode; }>'.

Property 'num' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Sample> & Readonly<{}> & Readonly<{ children?: ReactNode; }>'. TS2322

7 | <React.Fragment>
8 | <p>Hello world</p>
> 9 | <Sample num={"5"} />
| ^
10 | </React.Fragment>
11 | );
12 | }

Typescriptでは型をちゃんと指定してあげなければなりません。

Sample.tsxを以下のように書き換えてみましょう。


Sample.tsx

import React from "react";

interface Props {
num: string;
}

class Sample extends React.Component<Props> {
render() {
return <p>{this.props.num}つ目のコンポーネント</p>;
}
}

export default Sample;


これで変数numがstring型であることを定義できました。

エラーも解消され、問題なく画面が表示されます。

スクリーンショット 2019-07-19 16.33.42.png


Stateを使ってみる

App.tsxを書き換えて、Stateを使って何かしら値を画面に出力してみます。

スクリーンショット 2019-07-19 16.45.26.png

スクリーンショット 2019-07-19 16.45.45.png

ボタンを押下されたら文言が変わるという単純な実装をしてみました。

JavaScriptを使ったReactならこのように書くと思います。


App.tsx

import React from "react";

import Sample from "./Sample";

class App extends React.Component {
constructor(props) {
super(props);

this.state = {
message: "最初のメッセージ"
};

this.handleClick = this.handleClick.bind(this);
}

handleClick() {
this.setState({
message: "ボタンが押されました"
});
}

render() {
return (
<React.Fragment>
<p>Hello world</p>
<Sample num={"5"} />

<p>{this.state.message}</p>
<button onClick={this.handleClick}>ボタン</button>
</React.Fragment>
);
}
}

export default App;


しかしこれではエラーになってしまいますね。

Propsのときと同様に、TypeScriptでは型の指定が必要です。

下記のように書き換えましょう。


App.tsx

import React from "react";

import Sample from "./Sample";

interface Props {}

interface State {
message: string;
}

class App extends React.Component<Props, State> {
constructor(props: Props) {
super(props);

this.state = {
message: "最初のメッセージ"
};

this.handleClick = this.handleClick.bind(this);
}

handleClick() {
this.setState({
message: "ボタンが押されました"
});
}

render() {
return (
<React.Fragment>
<p>Hello world</p>
<Sample num={"5"} />

<p>{this.state.message}</p>
<button onClick={this.handleClick}>ボタン</button>
</React.Fragment>
);
}
}

export default App;


これで問題なく画面が表示されました。


参考

TypeScriptチュートリアル① -環境構築編-

TypeScript チュートリアル

React における State と Props の違い

今からはじめるReact.js〜propsとstate、それからrefs〜