- 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 APP中引入事件
- ReactJS - 状态管理
- ReactJS - 状态管理 API
- ReactJS - 无状态组件
- ReactJS - 使用 React Hooks 进行状态管理
- ReactJS - 使用 React 钩子的组件生命周期
- ReactJS - 组件的布局
- ReactJS - 分页
- ReactJS - Material 用户界面
- ReactJS - Http 客户端编程
- ReactJS - 表单编程
- ReactJS - 受控组件
- ReactJS - 不受控制的组件
- ReactJS - Formik
- ReactJS - 条件渲染
- ReactJS - 列表
- ReactJS - 键
- ReactJS - 路由
- ReactJS - 冗余
- ReactJS - 动画
- ReactJS - 引导程序
- ReactJS - 地图
- ReactJS - 表格
- ReactJS - 使用 Flux 管理状态
- ReactJS - 测试
- ReactJS - CLI 命令
- ReactJS - 构建和部署
- ReactJS - 示例
- ReactJS - 钩子简介
- ReactJS - 使用 useState
- ReactJS - 使用 useEffect
- ReactJS - 使用 useContext
- ReactJS - 使用 useRef
- ReactJS - 使用 useReducer
- ReactJS - 使用 useCallback
- ReactJS - 使用 useMemo
- ReactJS - 自定义钩子
- ReactJS - 可访问性
- ReactJS - 代码拆分
- ReactJS - 上下文
- ReactJS - 错误边界
- ReactJS - 转发引用
- ReactJS - 片段
- ReactJS - 高阶组件
- ReactJS - 与其他库集成
- ReactJS - 优化性能
- ReactJS - 分析器 API
- ReactJS - 门户
- ReactJS - 没有 ES6 ECMAScript 的 React
- ReactJS - 没有 JSX 的 React
- ReactJS - 协调
- ReactJS - 引用和 DOM
- ReactJS - 渲染属性
- ReactJS - 静态类型检查
- ReactJS - 严格模式
- ReactJS - Web 组件
- ReactJS - 日期选择器
- ReactJS - Helmet
- ReactJS - 内联样式
- ReactJS - 属性类型
- ReactJS - 浏览器路由器
- ReactJS - DOM
- ReactJS - 旋转木马
- ReactJS - 图标
- ReactJS - 表单组件
- ReactJS - 参考 API
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 注解使流静态检查器能够分析下面定义的函数。如您所见,函数 sum 使用 Flow 语言扩展来指定参数的类型。让我们看看如何在 react 项目中启用 Flow,以及启用 Flow 的 react 项目的开发工作流程。
第 1 步 - 使用 create-react-app CLI 应用程序创建新的 react 项目。
第 2 步 - 使用以下命令将Flow添加到项目中
npm install --save-bin flow-bin
第 3 步 - 现在,在package.json文件的脚本中添加Flow命令
{
// ...
"scripts": {
"flow": "flow",
// ...
},
// ...
}
这将允许我们通过 npm 运行流命令
第 4 步 - 使用flow命令初始化flow配置,如下所示 -
这将在项目的根目录中创建一个基本流程配置文件 .flowconfig,内容如下。
[include]
[libs]
[lints]
[options]
[strict]
可以在此处添加高级流程选项。默认情况下,flow 将检查我们应用程序中的所有文件。要忽略node_modules,请在 [忽略] 选项下添加 .*/node_modules/.*。这将指示流应用程序忽略 node_modules 文件夹中的所有文件。
.*/node_modules/.*
[include]
[libs]
[lints]
[options]
react.runtime=automatic
[strict]
第 5 步 - 现在,我们已经配置了应用程序的流程。我们可以在代码中使用流注释,并使用以下命令针对流进行测试
Flow 将检查我们的代码并在控制台中显示类似的结果,如下所示 -
> 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 命令来检查代码的正确性。创建一个简单的 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 命令将检查代码并显示错误,即名称设置为字符串值,如下所示。
> 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 命令将成功,并显示代码中没有问题。
> flow
No errors!
第 10 步 - 最后,我们可以通过运行以下命令来运行该应用程序,
可以使用以下命令创建优化的生产版本,
TypeScript
TypeScript 是一种对静态类型提供一流支持的语言。静态类型使 TypeScript 能够在编译时而不是运行时捕获类型错误。TypeScript 支持 JavaScript 的所有语言特性。
因此,对于 JavaScript 开发人员来说,使用 TypeScript 真的很容易。React 内置了对 TypeScript 的支持。要创建 React 项目,只需在创建 react 应用程序期间通过 create-react-app 包含 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。让我们运行应用程序并检查编译器是否捕获了错误。
运行命令会抛出错误,如下所示 -
...
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组件中抛出错误,如下所示 -
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
最后,我们的代码被编译完毕,没有错误,如下所示,并且可以在 'http://localhost:3000/