- 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 将检查我们的代码并在控制台中显示类似以下的结果:
> [email protected] 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 设置为字符串值的错误,如下所示。
> [email protected] 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 命令将成功并显示代码中没有问题。
> [email protected] 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://127.0.0.1:3000/` 查看。
No issues found.