React NativeでTypeScriptを使用する
JavaScript!私たちは皆大好きです。しかし、中には型が好きな人もいます。幸いなことに、JavaScriptに強力な型を追加する選択肢は存在します。私のお気に入りはTypeScriptですが、React NativeはFlowを標準でサポートしています。どちらを好むかは好みの問題であり、それぞれがJavaScriptに型の魔法を追加するための独自のアプローチを持っています。今日は、React NativeアプリでTypeScriptを使用する方法について見ていきましょう。
この記事では、MicrosoftのTypeScript-React-Native-Starterリポジトリをガイドとして使用します。
更新: このブログ記事が書かれてから、さらに簡単になりました。このブログ記事で説明されているセットアップはすべて、たった1つのコマンドを実行するだけで置き換えられます。
npx react-native init MyAwesomeProject --template react-native-template-typescript
ただし、BabelのTypeScriptサポートにはいくつかの制限があり、上記のブログ記事で詳しく説明されています。この記事で概説されている手順はまだ機能し、Artsyは本番環境でまだreact-native-typescript-transformerを使用していますが、React NativeとTypeScriptを使い始める最速の方法は上記のコマンドを使用することです。必要であれば、後で切り替えることもいつでもできます。
いずれにせよ、楽しんでください!元のブログ記事は以下に続きます。
前提条件
あなたはいくつかの異なるプラットフォームで開発し、いくつかの異なるタイプのデバイスをターゲットにしている可能性があるため、基本的なセットアップは複雑になることがあります。まず、TypeScriptなしでプレーンなReact Nativeアプリを実行できることを確認する必要があります。React Nativeのウェブサイトの指示に従って始めてください。デバイスやエミュレータにデプロイできたら、TypeScript React Nativeアプリを開始する準備が整います。
初期化
通常のReact Nativeプロジェクトのひな形を作成してみたら、TypeScriptを追加する準備が整います。さあ、やってみましょう。
react-native init MyAwesomeProject
cd MyAwesomeProject
TypeScriptの追加
次のステップは、プロジェクトにTypeScriptを追加することです。以下のコマンドは、
- プロジェクトにTypeScriptを追加します
- プロジェクトにReact Native TypeScript Transformerを追加します
- 空のTypeScript設定ファイルを初期化します。これは次に設定します
- 空のReact Native TypeScript Transformer設定ファイルを追加します。これは次に設定します
- ReactとReact Nativeの型定義を追加します
では、これらを実行してみましょう。
yarn add --dev typescript
yarn add --dev react-native-typescript-transformer
yarn tsc --init --pretty --jsx react
touch rn-cli.config.js
yarn add --dev @types/react @types/react-native
tsconfig.json
ファイルにはTypeScriptコンパイラのすべての設定が含まれています。上記のコマンドで作成されたデフォルトはほとんど問題ありませんが、ファイルを開いて次の行のコメントを解除してください。
{
/* Search the config file for the following line and uncomment it. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
}
rn-cli.config.js
にはReact Native TypeScript Transformerの設定が含まれています。それを開いて以下を追加してください。
module.exports = {
getTransformModulePath() {
return require.resolve('react-native-typescript-transformer');
},
getSourceExts() {
return ['ts', 'tsx'];
},
};
TypeScriptへの移行
生成されたApp.js
と__tests_/App.js
ファイルをApp.tsx
にリネームします。index.js
は.js
拡張子を使用する必要があります。新しいファイルはすべて.tsx
拡張子を使用する必要があります(ファイルにJSXが含まれていない場合は.ts
)。
もし今アプリを実行しようとすると、object prototype may only be an object or null
のようなエラーが表示されるでしょう。これは、Reactからのデフォルトエクスポートと名前付きエクスポートを同じ行でインポートしようとしたために発生します。App.tsx
を開き、ファイルの先頭にあるインポート文を修正してください。
-import React, { Component } from 'react';
+import React from 'react'
+import { Component } from 'react';
これの一部は、BabelとTypeScriptがCommonJSモジュールと相互運用する方法の違いに関係しています。将来的には、両者は同じ挙動に安定するでしょう。
この時点で、React Nativeアプリを実行できるはずです。
TypeScriptテストインフラの追加
React NativeにはJestが同梱されているので、React NativeアプリをTypeScriptでテストするには、ts-jestをdevDependencies
に追加する必要があります。
yarn add --dev ts-jest
次に、package.json
を開き、jest
フィールドを以下に置き換えます。
{
"jest": {
"preset": "react-native",
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"transform": {
"^.+\\.(js)$": "<rootDir>/node_modules/babel-jest",
"\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"testPathIgnorePatterns": [
"\\.snap$",
"<rootDir>/node_modules/"
],
"cacheDirectory": ".jest/cache"
}
}
これにより、Jestは.ts
および.tsx
ファイルをts-jest
で実行するように設定されます。
依存関係の型定義ファイルのインストール
TypeScriptで最高のエクスペリエンスを得るためには、型チェッカーが依存関係の構造とAPIを理解する必要があります。一部のライブラリは、パッケージを.d.ts
ファイル(型宣言/型定義ファイル)と共に公開しており、これらは基礎となるJavaScriptの構造を記述できます。他のライブラリについては、@types/
npmスコープで適切なパッケージを明示的にインストールする必要があります。
たとえば、ここではJest、React、React Native、およびReact Test Rendererの型が必要になります。
yarn add --dev @types/jest @types/react @types/react-native @types/react-test-renderer
これらの宣言ファイルパッケージは、開発中にのみこれらの依存関係を使用し、ランタイムでは使用しないReact Native *アプリ* であるため、*dev* 依存関係として保存しました。NPMにライブラリを公開している場合は、これらの型依存関係の一部を通常の依存関係として追加する必要があるかもしれません。
.d.ts
ファイルの入手方法についてはこちらで詳しく読むことができます。
無視するファイルの追加
ソース管理では、.jest
フォルダを無視するように設定する必要があります。gitを使用している場合は、.gitignore
ファイルにエントリを追加するだけです。
# Jest
#
.jest/
チェックポイントとして、ファイルをバージョン管理にコミットすることを検討してください。
git init
git add .gitignore # import to do this first, to ignore our files
git add .
git commit -am "Initial commit."
コンポーネントの追加
アプリにコンポーネントを追加しましょう。Hello.tsx
コンポーネントを作成します。これは教育的なコンポーネントであり、実際にアプリで書くようなものではありませんが、React NativeでTypeScriptを使用する方法を示すための、ある程度複雑なものです。
components
ディレクトリを作成し、以下の例を追加してください。
// components/Hello.tsx
import React from 'react';
import {Button, StyleSheet, Text, View} from 'react-native';
export interface Props {
name: string;
enthusiasmLevel?: number;
}
interface State {
enthusiasmLevel: number;
}
export class Hello extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
if ((props.enthusiasmLevel || 0) <= 0) {
throw new Error(
'You could be a little more enthusiastic. :D',
);
}
this.state = {
enthusiasmLevel: props.enthusiasmLevel || 1,
};
}
onIncrement = () =>
this.setState({
enthusiasmLevel: this.state.enthusiasmLevel + 1,
});
onDecrement = () =>
this.setState({
enthusiasmLevel: this.state.enthusiasmLevel - 1,
});
getExclamationMarks = (numChars: number) =>
Array(numChars + 1).join('!');
render() {
return (
<View style={styles.root}>
<Text style={styles.greeting}>
Hello{' '}
{this.props.name +
this.getExclamationMarks(this.state.enthusiasmLevel)}
</Text>
<View style={styles.buttons}>
<View style={styles.button}>
<Button
title="-"
onPress={this.onDecrement}
accessibilityLabel="decrement"
color="red"
/>
</View>
<View style={styles.button}>
<Button
title="+"
onPress={this.onIncrement}
accessibilityLabel="increment"
color="blue"
/>
</View>
</View>
</View>
);
}
}
// styles
const styles = StyleSheet.create({
root: {
alignItems: 'center',
alignSelf: 'center',
},
buttons: {
flexDirection: 'row',
minHeight: 70,
alignItems: 'stretch',
alignSelf: 'center',
borderWidth: 5,
},
button: {
flex: 1,
paddingVertical: 0,
},
greeting: {
color: '#999',
fontWeight: 'bold',
},
});
おお!たくさんありますが、分解してみましょう。
div
、span
、h1
などのHTML要素をレンダリングする代わりに、View
やButton
などのコンポーネントをレンダリングしています。これらは、異なるプラットフォームで動作するネイティブコンポーネントです。- スタイリングは、React Nativeが提供する
StyleSheet.create
関数を使用して指定されます。Reactのスタイルシートを使用すると、Flexboxを使用してレイアウトを制御したり、CSSの他の構成要素に似たものを使用してスタイルを設定したりできます。
コンポーネントテストの追加
コンポーネントができたので、テストしてみましょう。
テストランナーとしてJestはすでにインストールされています。コンポーネントのスナップショットテストを記述するので、スナップショットテストに必要なアドオンを追加しましょう。
yarn add --dev react-addons-test-utils
それでは、components
ディレクトリに__tests__
フォルダを作成し、Hello.tsx
のテストを追加しましょう。
// components/__tests__/Hello.tsx
import React from 'react';
import renderer from 'react-test-renderer';
import {Hello} from '../Hello';
it('renders correctly with defaults', () => {
const button = renderer
.create(<Hello name="World" enthusiasmLevel={1} />)
.toJSON();
expect(button).toMatchSnapshot();
});
テストが初めて実行されると、レンダリングされたコンポーネントのスナップショットが作成され、components/__tests__/__snapshots__/Hello.tsx.snap
ファイルに保存されます。コンポーネントを変更した場合は、スナップショットを更新し、意図しない変更がないかレビューする必要があります。React Nativeコンポーネントのテストについては、こちらで詳しく読むことができます。
次のステップ
公式のReactチュートリアルや状態管理ライブラリのReduxをチェックしてみてください。これらのリソースは、React Nativeアプリを作成する際に役立ちます。さらに、Web上のReactとReact Nativeの両方をサポートする、完全にTypeScriptで書かれたコンポーネントライブラリであるReactXPも見てみると良いでしょう。
より型安全なReact Native開発環境で楽しんでください!