
- ReactJS 教程
- ReactJS - 首頁
- ReactJS - 簡介
- ReactJS - 路線圖
- ReactJS - 安裝
- ReactJS - 特性
- ReactJS - 優點與缺點
- ReactJS - 架構
- ReactJS - 建立 React 應用
- ReactJS - JSX
- ReactJS - 元件
- ReactJS - 巢狀元件
- ReactJS - 使用新建立的元件
- ReactJS - 元件集合
- ReactJS - 樣式
- ReactJS - 屬性 (props)
- ReactJS - 使用屬性建立元件
- ReactJS - props 驗證
- ReactJS - 建構函式
- ReactJS - 元件生命週期
- ReactJS - 事件管理
- ReactJS - 建立一個事件感知元件
- ReactJS - 在 Expense Manager 應用中引入事件
- ReactJS - 狀態管理
- ReactJS - 狀態管理 API
- ReactJS - 無狀態元件
- ReactJS - 使用 React Hooks 進行狀態管理
- ReactJS - 使用 React Hooks 進行元件生命週期管理
- ReactJS - 佈局元件
- ReactJS - 分頁
- ReactJS - Material UI
- ReactJS - Http 客戶端程式設計
- ReactJS - 表單程式設計
- ReactJS - 受控元件
- ReactJS - 非受控元件
- ReactJS - Formik
- ReactJS - 條件渲染
- ReactJS - 列表
- ReactJS - Keys
- ReactJS - 路由
- ReactJS - Redux
- ReactJS - 動畫
- ReactJS - Bootstrap
- ReactJS - 地圖
- ReactJS - 表格
- ReactJS - 使用 Flux 管理狀態
- ReactJS - 測試
- ReactJS - CLI 命令
- ReactJS - 構建與部署
- ReactJS - 示例
- Hooks
- ReactJS - Hooks 簡介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定義 Hooks
- ReactJS 高階
- ReactJS - 可訪問性
- ReactJS - 程式碼分割
- ReactJS - 上下文
- ReactJS - 錯誤邊界
- ReactJS - 轉發 Refs
- ReactJS - 碎片
- ReactJS - 高階元件
- ReactJS - 整合其他庫
- ReactJS - 最佳化效能
- ReactJS - Profiler API
- ReactJS - 門戶
- ReactJS - 無 ES6 ECMAScript 的 React
- ReactJS - 無 JSX 的 React
- ReactJS - 調和
- ReactJS - Refs 和 DOM
- ReactJS - 渲染 Props
- ReactJS - 靜態型別檢查
- ReactJS - 嚴格模式
- ReactJS - Web Components
- 其他概念
- ReactJS - 日期選擇器
- ReactJS - Helmet
- ReactJS - 內聯樣式
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - 走馬燈
- ReactJS - 圖示
- ReactJS - 表單元件
- ReactJS - 參考 API
- ReactJS 有用資源
- ReactJS - 快速指南
- ReactJS - 有用資源
- ReactJS - 討論
ReactJS - 靜態型別檢查
由於 JavaScript 是一種動態型別語言,因此在執行程式碼之前很難發現型別不匹配錯誤。React 透過 prop-types 包支援對 props 進行型別檢查,可以在開發階段使用它來識別屬性的型別不匹配。
程式的其他方面仍然需要一個工具來在開發階段正確識別型別問題。JavaScript 有很多靜態型別檢查器工具來處理型別問題。我們將檢查兩個流行的選項,它們可以平滑地整合到 React 應用程式的工作流程中,並在應用程式的開發階段提供可能的型別錯誤提示。它們如下所示:
Flow
TypeScript 語言
Flow
Flow 是 JavaScript 的靜態型別檢查器。Flow 擴充套件了 JavaScript 語言以指定型別,並允許在 JavaScript 程式碼中設定靜態型別註釋。Flow 將檢查開發人員在程式碼中設定的靜態型別註釋,並確保使用了正確的型別。否則,它將丟擲錯誤。一個簡單的例子如下所示:
// @flow function sum(a: number, b: number) : number { return a + b; } sum(10, 20) // Pass sum("10", "20") // Fail
這裡,// @flow 註釋使 Flow 靜態檢查器能夠分析下面定義的函式。如您所見,函式 sum 使用 Flow 語言擴充套件來指定引數的型別。讓我們看看如何在 React 專案中啟用 Flow 以及啟用 Flow 的 React 專案的開發工作流程。
步驟 1 - 使用 create-react-app CLI 應用建立一個新的 React 專案。
create-react-app myapp
步驟 2 - 使用以下命令將 Flow 新增到專案中
cd myapp npm install --save-bin flow-bin
步驟 3 - 現在,在 package.json 檔案的 scripts 中新增 Flow 命令
{ // ... "scripts": { "flow": "flow", // ... }, // ... }
這將允許我們透過 npm 執行 flow 命令
步驟 4 - 使用以下命令初始化 Flow 配置:
npm run flow init
這將在專案的根目錄建立一個基本的 Flow 配置檔案 .flowconfig,其內容如下。
[ignore] [include] [libs] [lints] [options] [strict]
可以在這裡新增高階 Flow 選項。預設情況下,Flow 將檢查我們應用程式中的所有檔案。要忽略 node_modules,請在 [ignore] 選項下新增 .*/node_modules/.*。這將指示 Flow 應用程式忽略 node_modules 資料夾中的所有檔案。
[ignore] .*/node_modules/.* [include] [libs] [lints] [options] react.runtime=automatic [strict]
步驟 5 - 現在,我們已將 Flow 配置到我們的應用程式中。我們可以在我們的程式碼中使用 Flow 註釋,並使用以下命令針對 Flow 進行測試
npm run flow
Flow 將檢查我們的程式碼並在控制檯中顯示類似以下的結果:
> myapp@0.1.0 flow /path/to/myapp > flow Launching Flow server for /path/to/myapp Spawned flow server (pid=1629) Logs will go to /private/tmp/flow/zSUserszSbalazSProjectszSArticleszSreact-revision-v2zSworkspacezSmyapp.log Monitor logs will go to /private/tmp/flow/zSUserszSbalazSProjectszSArticleszSreact-revision-v2zSworkspacezSmyapp.monitor_log No errors!
步驟 6 - 現在,可以使用 Flow 註釋在我們的程式碼中。讓我們在我們的程式碼中新增一個簡單的 Flow 註釋,並執行 flow 命令來檢查程式碼的正確性。建立一個簡單的 HelloWorld 元件(src/components/HelloWorld.js),如下所示:
import React from 'react' class HelloWorld extends React.Component { render() { return <h1>Hello, {this.props.name}</h1> } } export default HelloWorld
步驟 7 - 將元件包含在我們的根元件(App.js)中,如下所示:
// @flow import React from "react"; import HelloWorld from "./components/HelloWorld"; function App() : any { var name: string = 10 return ( <div> <HelloWorld name={name} /> </div> ) } export default App;
步驟 8 - 現在,使用 flow 檢查程式碼,如下所示
npm run flow
Flow 命令將檢查程式碼並顯示 name 設定為字串值的錯誤,如下所示。
> myapp@0.1.0 flow /path/to/myapp > flow Error ............................................src/App.js:6:22 Cannot assign 10 to name because number [1] is incompatible with string [2]. [incompatible-type] 3│ import HelloWorld from "./components/HelloWorld"; 4│ 5│ function App() : any { [2][1]6│ var name: string = 10 7│ 8│ return ( 9│ <div> Found 1 error ..... .....
步驟 9 - 讓我們透過為 name 變數提供一個字串值來修復錯誤,並重新執行 flow 命令。
// @flow import React from "react"; import HelloWorld from "./components/HelloWorld"; function App() : any { var name: string = "John" return ( <div> <HelloWorld name={name} /> </div> ) } export default App;
現在,flow 命令將成功並顯示程式碼中沒有問題。
> myapp@0.1.0 flow /path/to/myapp > flow No errors!
步驟 10 - 最後,我們可以透過執行以下命令來執行應用程式,
npm start
可以使用以下命令建立最佳化的生產版本,
npm run build
TypeScript
TypeScript 是一種對靜態型別具有一流支援的語言。靜態型別使 TypeScript 能夠在編譯時而不是執行時捕獲型別錯誤。TypeScript 支援 JavaScript 的所有語言特性。
因此,對於 JavaScript 開發人員來說,使用 TypeScript 非常容易。React 對 TypeScript 具有內建支援。要建立 React 專案,只需在透過 create-react-app 建立 React 應用期間包含 TypeScript 模板即可。
create-react-app myapp --template typescript
建立應用程式後,在 src/components 資料夾下新增一個新的 HelloWorld 元件 (HelloWorld.tsx),如下所示:
// src/components/HelloWorld.tsx import React from 'react' class HelloWorld extends React.Component { render() { return <h1>Hello, {this.props.name}</h1> } } export default HelloWorld
現在,包含 HelloWorld 元件 -
import React from "react"; import HelloWorld from "./components/HelloWorld"; function App() : any { var name: string = 10 return ( <div> <HelloWorld name={name} /> </div> ) } export default App;
在這裡,我們故意將 name 的值設定為 10。讓我們執行應用程式並檢查編譯器是否捕獲錯誤。
npm start
執行該命令會丟擲錯誤,如下所示:
... ... ERROR in src/App.tsx:5:7 TS2322: Type 'number' is not assignable to type 'string'. 3 | 4 | function App() : any { > 5 | var name: string = 10 | ^^^^ 6 | 7 | return ( 8 | <div> ... ...
讓我們更改 name 的值並設定一個字串值("John")。上述錯誤已修復,但編譯器仍在 HelloWorld 元件中丟擲錯誤,如下所示:
Issues checking in progress... ERROR in src/App.tsx:9:19 TS2769: No overload matches this call. Overload 1 of 2, '(props: {} | Readonly<{}>): HelloWorld', gave the following error. Type '{ name: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<HelloWorld> & Readonly<{}>'. Property 'name' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<HelloWorld> & Readonly<{}>'. Overload 2 of 2, '(props: {}, context: any): HelloWorld', gave the following error. Type '{ name: string; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<HelloWorld> & Readonly<{}>'. Property 'name' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<HelloWorld> & Readonly<{}>'. 7 | return ( 8 | <div> > 9 | <HelloWorld name={name} /> | ^^^^ 10 | </div> 11 | ) 12 | } ERROR in src/components/HelloWorld.tsx:9:39 TS2339: Property 'name' does not exist on type 'Readonly<{}>'. 7 | class HelloWorld extends React.Component { 8 | render() { > 9 | return <h1>Hello, {this.props.name}</h1> | ^^^^ 10 | } 11 | } 12 |
要修復錯誤,應為 HelloWorld 元件提供其屬性的型別資訊。為屬性建立一個新的介面,然後將其包含在 HelloWorld 元件中,如下所示:
import React from 'react' interface HelloWorldProps { name: string } class HelloWorld extends React.Component<HelloWorldProps> { render() { return <h1>Hello, {this.props.name}</h1> } } export default HelloWorld
最後,我們的程式碼在沒有錯誤的情況下編譯,如下所示,並且可以透過 `https://:3000/` 檢視。
No issues found.
