使用 TypeScript 與 React Native
JavaScript!我們都喜歡它。但我們有些人也喜歡型別。幸運的是,有許多選項可以為 JavaScript 新增更強大的型別。我最喜歡的是 TypeScript,但 React Native 開箱即用就支援 Flow。您偏好哪一個是個人喜好問題,它們各自有自己的方法來為 JavaScript 新增型別的魔力。今天,我們將看看如何在 React Native 應用程式中使用 TypeScript。
這篇文章使用 Microsoft 的 TypeScript-React-Native-Starter 存放庫作為指南。
更新:自這篇部落格文章撰寫以來,事情變得更加容易。您可以執行一個命令,即可取代這篇部落格文章中描述的所有設定
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,因此為了使用 TypeScript 測試 React Native 應用程式,我們會想要將 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-jest
執行 .ts
和 .tsx
檔案。
安裝相依性類型宣告
為了在 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應用程式,僅在開發期間使用這些相依性,而不在執行階段使用。如果我們要將函式庫發布到 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 應用程式時可能會有所幫助。此外,您可能還想看看 ReactXP,這是一個完全以 TypeScript 編寫的組件函式庫,同時支援網頁上的 React 和 React Native。
在更具型別安全性的 React Native 開發環境中玩得開心!