2022-10-04 00:56:09 +08:00
|
|
|
|
React 备忘清单
|
|
|
|
|
===
|
|
|
|
|
|
2022-12-03 14:54:19 +08:00
|
|
|
|
[](https://npmjs.org/package/react)
|
|
|
|
|
[](https://www.npmjs.com/package/react)
|
|
|
|
|
[](https://github.com/facebook/react/network/dependents)
|
|
|
|
|
[](https://github.com/facebook/react)
|
|
|
|
|
|
2022-12-03 17:55:09 +08:00
|
|
|
|
适合初学者的综合 React 备忘清单
|
2022-12-03 14:54:19 +08:00
|
|
|
|
<!--rehype:style=padding-top: 12px;-->
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
|
|
|
|
入门
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
### 介绍
|
|
|
|
|
|
2022-12-03 14:54:19 +08:00
|
|
|
|
React 是一个用于构建用户界面的 JavaScript 库
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
|
|
|
|
- [React 官方文档](https://reactjs.org/) _(reactjs.org)_
|
2022-10-09 00:56:32 +08:00
|
|
|
|
- [Styled Components 备忘清单](./styled-components.md) _(jaywcjlove.github.io)_
|
2022-12-03 17:44:28 +08:00
|
|
|
|
- [TypeScript JSX 备忘清单](./typescript.md#jsx) _(jaywcjlove.github.io)_
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
import {createRoot} from 'react-dom/client'
|
|
|
|
|
import App from './App'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const elm = document.getElementById('app')
|
|
|
|
|
const root = createRoot(elm);
|
|
|
|
|
root.render(<App />);
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-05 02:51:57 +08:00
|
|
|
|
#### 快速创建 **React** 项目 ([CRA](https://github.com/facebook/create-react-app))
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
npx create-react-app my-app
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-04 00:56:09 +08:00
|
|
|
|
### 导入多个导出
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
import React, {Component} from 'react'
|
|
|
|
|
import ReactDOM from 'react-dom'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
-----
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
export class Hello extends Component {
|
|
|
|
|
...
|
|
|
|
|
}
|
2022-10-09 00:56:32 +08:00
|
|
|
|
export default function World() {
|
|
|
|
|
/* ... */
|
|
|
|
|
}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-10-09 00:56:32 +08:00
|
|
|
|
使用 `export` 导出 **`Hello`**,`export default` 导出 **`World`** 组件
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
|
|
|
|
```jsx
|
2022-10-09 00:56:32 +08:00
|
|
|
|
import World, { Hello } from './hello.js';
|
2022-10-04 00:56:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
使用 `import` 导入 `Hello` 组件,在示例中使用。
|
|
|
|
|
|
|
|
|
|
### React 组件中的 CSS
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {2,5}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
import React from "react";
|
|
|
|
|
import "./Student.css";
|
|
|
|
|
|
|
|
|
|
export const Student = (
|
|
|
|
|
<div className="Student"></div>
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
注意:类属性 `className`
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const divStyle = {
|
|
|
|
|
backgroundImage: 'url(' + imgUrl + ')',
|
|
|
|
|
};
|
|
|
|
|
export const Student = (
|
|
|
|
|
<div style={divStyle}></div>
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 属性
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<Student name="Julie" age={23}
|
|
|
|
|
pro={true} />
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
函数组件 `Student` 中访问属性
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function Student(props) {
|
|
|
|
|
return <h1>Hello, {props.name}</h1>;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Class 组件 `Student` 中访问属性
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
class Student extends React.Component {
|
|
|
|
|
render() {
|
|
|
|
|
return (
|
|
|
|
|
<h1>Hello, {this.props.name}</h1>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`class` 组件使用 `this.props` 访问传递给组件的属性。
|
|
|
|
|
|
|
|
|
|
### Children
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function Example() {
|
|
|
|
|
return (
|
|
|
|
|
<AlertBox>
|
|
|
|
|
<h1>您有待处理的通知</h1>
|
|
|
|
|
</AlertBox>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
函数 `AlertBox` 组件
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {4}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
function AlertBox(props) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="alert-box">
|
|
|
|
|
{props.children}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-11-11 01:51:54 +08:00
|
|
|
|
-----
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
{props.children}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Class `AlertBox` 组件,与函数组件 `AlertBox` 组件相同
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {5}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
class AlertBox extends React.Component {
|
|
|
|
|
render () {
|
|
|
|
|
return (
|
|
|
|
|
<div className="alert-box">
|
|
|
|
|
{this.props.children}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-11-11 01:51:54 +08:00
|
|
|
|
-----
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
{this.props.children}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`children` 作为子组件的的属性传递。
|
|
|
|
|
|
|
|
|
|
### State
|
|
|
|
|
<!--rehype:wrap-class=row-span-3-->
|
|
|
|
|
|
|
|
|
|
函数中的 State,Hook 是 React 16.8 的新增特性
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {4,8}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
import { useState } from 'react';
|
|
|
|
|
|
|
|
|
|
function Student() {
|
|
|
|
|
const [count, setCount] = useState(0);
|
|
|
|
|
const click = () => setCount(count + 1);
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<p>您点击了 {count} 次</p>
|
|
|
|
|
<button onClick={click}>
|
|
|
|
|
点击我
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
使用 `setState` 更新状态,下面是函数组件读取状态
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<p>您点击了 {count} 次</p>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Class 中的 State
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {6,12,20}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
import React from 'react';
|
|
|
|
|
|
|
|
|
|
class Student extends React.Component {
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {count: 1};
|
2022-10-05 14:46:37 +08:00
|
|
|
|
// 确保函数可以访问组件属性(ES2015)
|
|
|
|
|
this.click = this.click.bind(this);
|
2022-10-04 00:56:09 +08:00
|
|
|
|
}
|
|
|
|
|
click() {
|
|
|
|
|
const count = this.state.count;
|
|
|
|
|
this.setState({ count: count + 1})
|
|
|
|
|
}
|
|
|
|
|
render() {
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<button onClick={this.click}>
|
|
|
|
|
点击我
|
|
|
|
|
</button>
|
|
|
|
|
<p>您点击了{this.state.count}次</p>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
使用 `setState` 更新状态,`class` 组件中不能使用 <yel>~~hooks~~</yel>。下面是 `class` 组件读取状态
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<p>您点击了{this.state.count}次</p>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 循环
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const elm = ['one', 'two', 'three'];
|
|
|
|
|
function Student() {
|
|
|
|
|
return (
|
|
|
|
|
<ul>
|
|
|
|
|
{elm.map((value, index) => (
|
|
|
|
|
<li key={index}>{value}</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`key` 值在兄弟节点之间必须唯一
|
|
|
|
|
|
|
|
|
|
### 事件监听
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
export default function Hello() {
|
|
|
|
|
function handleClick(event) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
alert("Hello World");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<a href="/" onClick={handleClick}>
|
|
|
|
|
Say Hi
|
|
|
|
|
</a>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 函数注入
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function addNumbers(x1, x2) {
|
|
|
|
|
return x1 + x2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const element = (
|
2022-10-05 02:43:18 +08:00
|
|
|
|
<div>
|
|
|
|
|
{addNumbers(2, 5)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2022-10-04 00:56:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 嵌套
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
import { useState } from 'react'
|
|
|
|
|
import Avatar from './Avatar';
|
|
|
|
|
import Profile from './Profile';
|
|
|
|
|
|
|
|
|
|
function Student() {
|
|
|
|
|
const [count, setCount] = useState(0);
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<Avatar src={count} />
|
|
|
|
|
<Profile username={count} />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-05 02:43:18 +08:00
|
|
|
|
### Portals
|
|
|
|
|
|
2022-11-11 01:51:54 +08:00
|
|
|
|
React 并_没有_创建一个新的 `div`。它只是把子元素渲染到 `domNode` 中。`domNode` 是一个可以在任何位置的有效 DOM 节点。
|
2022-10-05 02:43:18 +08:00
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
render() {
|
|
|
|
|
return ReactDOM.createPortal(
|
|
|
|
|
this.props.children,
|
|
|
|
|
domNode
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案
|
|
|
|
|
|
2022-10-04 00:56:09 +08:00
|
|
|
|
### Fragment
|
2022-10-05 02:43:18 +08:00
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {1,6,9}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
import { Fragment } from 'react'
|
|
|
|
|
import Avatar from './Avatar';
|
|
|
|
|
import Profile from './Profile';
|
|
|
|
|
|
|
|
|
|
const Student = () => (
|
|
|
|
|
<Fragment>
|
|
|
|
|
<Avatar src="./demo.jpg" />
|
|
|
|
|
<Profile username="name" />
|
|
|
|
|
</Fragment>
|
2022-10-05 02:43:18 +08:00
|
|
|
|
);
|
2022-10-04 00:56:09 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-10-04 11:19:03 +08:00
|
|
|
|
从 `v16.2.0` 开始 `Fragment` 可用于返回多个子节点,而无需向 DOM 添加额外的包装节点。或者使用 `<></>` 效果是一样的。
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
2022-10-06 02:20:53 +08:00
|
|
|
|
```jsx {2,5}
|
2022-10-05 02:43:18 +08:00
|
|
|
|
const Student = () => (
|
|
|
|
|
<>
|
|
|
|
|
<Avatar src="./demo.jpg" />
|
|
|
|
|
<Profile username="name" />
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
```
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
2022-10-05 02:43:18 +08:00
|
|
|
|
查看: [Fragments & strings](https://reactjs.org/blog/2017/09/26/react-v16.0.html#new-render-return-types-fragments-and-strings)
|
|
|
|
|
|
|
|
|
|
### 返回字符串
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
2022-10-06 02:20:53 +08:00
|
|
|
|
```jsx {2}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
render() {
|
2022-10-05 02:43:18 +08:00
|
|
|
|
return 'Look ma, no spans!';
|
2022-10-04 00:56:09 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-05 02:43:18 +08:00
|
|
|
|
您可以只返回一个字符串。查看: [Fragments & strings](https://reactjs.org/blog/2017/09/26/react-v16.0.html#new-render-return-types-fragments-and-strings)
|
|
|
|
|
|
|
|
|
|
### 返回数组
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const Student = () => [
|
|
|
|
|
<li key="A">First item</li>,
|
|
|
|
|
<li key="B">Second item</li>
|
|
|
|
|
];
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
不要忘记 `key`!查看: [Fragments & strings](https://reactjs.org/blog/2017/09/26/react-v16.0.html#new-render-return-types-fragments-and-strings)
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
2022-10-04 11:19:03 +08:00
|
|
|
|
### Refs 转发
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const FancyButton = React.forwardRef(
|
|
|
|
|
(props, ref) => (
|
|
|
|
|
<button ref={ref} className="btn">
|
|
|
|
|
{props.children}
|
|
|
|
|
</button>
|
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 使用
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
// 你可以直接获取 DOM button 的 ref:
|
|
|
|
|
const ref = React.createRef();
|
|
|
|
|
|
|
|
|
|
<FancyButton ref={ref}>
|
|
|
|
|
点击我
|
|
|
|
|
</FancyButton>;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Class 组件内部使用 ref 属性
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {6,10}
|
2022-10-05 02:43:18 +08:00
|
|
|
|
import {Component,createRef} from 'react'
|
2022-10-04 11:19:03 +08:00
|
|
|
|
|
|
|
|
|
class MyComponent extends Component {
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.myRef = createRef();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
return <div ref={this.myRef} />;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
提示:Refs 适用于类组件,但不适用于函数组件(除非您使用 useRef hook,请参阅[hooks](#hooks))
|
|
|
|
|
|
|
|
|
|
### 函数组件内部使用 ref 属性
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {3,9}
|
2022-10-04 11:19:03 +08:00
|
|
|
|
function CustomTextInput(props) {
|
|
|
|
|
// 这里必须声明 $input,这样 ref 才可以引用它
|
|
|
|
|
const $input = useRef(null);
|
|
|
|
|
function handleClick() {
|
|
|
|
|
$input.current.focus();
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<input type="text" ref={$input} />
|
|
|
|
|
<input
|
|
|
|
|
type="button" value="聚焦文本输入"
|
|
|
|
|
onClick={handleClick}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-05 01:34:11 +08:00
|
|
|
|
### 严格模式 StrictMode
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {3,8}
|
2022-10-05 01:34:11 +08:00
|
|
|
|
<div>
|
|
|
|
|
<Header />
|
|
|
|
|
<React.StrictMode>
|
|
|
|
|
<div>
|
|
|
|
|
<ComponentOne />
|
|
|
|
|
<ComponentTwo />
|
|
|
|
|
</div>
|
|
|
|
|
</React.StrictMode>
|
|
|
|
|
<Footer />
|
|
|
|
|
</div>
|
|
|
|
|
```
|
|
|
|
|
|
2022-11-11 01:51:54 +08:00
|
|
|
|
-----
|
2022-10-05 01:34:11 +08:00
|
|
|
|
|
|
|
|
|
- [识别不安全的生命周期](https://zh-hans.reactjs.org/docs/strict-mode.html#identifying-unsafe-lifecycles)
|
|
|
|
|
- [关于使用过时字符串 ref API 的警告](https://zh-hans.reactjs.org/docs/strict-mode.html#warning-about-legacy-string-ref-api-usage)
|
|
|
|
|
- [关于使用废弃的 findDOMNode 方法的警告](https://zh-hans.reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage)
|
|
|
|
|
- [检测意外的副作用](https://zh-hans.reactjs.org/docs/strict-mode.html#detecting-unexpected-side-effects)
|
|
|
|
|
- [检测过时的 context API](https://zh-hans.reactjs.org/docs/strict-mode.html#detecting-legacy-context-api)
|
|
|
|
|
- [确保可复用的状态](https://zh-hans.reactjs.org/docs/strict-mode.html#ensuring-reusable-state)
|
|
|
|
|
|
|
|
|
|
突出显示应用程序中潜在问题的工具。请参阅:[严格模式](https://zh-hans.reactjs.org/docs/strict-mode.html)
|
|
|
|
|
|
|
|
|
|
### Profiler
|
|
|
|
|
<!--rehype:wrap-class=col-span-2-->
|
|
|
|
|
|
|
|
|
|
测量一个 React 应用多久渲染一次以及渲染一次的 `代价`
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<Profiler id="Navigation" onRender={callback}>
|
|
|
|
|
<Navigation {...props} />
|
|
|
|
|
</Profiler>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
为了分析 `Navigation` 组件和它的子代。应该在需要时才去使用它。
|
|
|
|
|
|
|
|
|
|
:- | :-
|
|
|
|
|
:- | :-
|
|
|
|
|
`id(string)` | 发生提交的 `Profiler` 树的 `id`
|
|
|
|
|
`onRender(function)` | 组件树任何组件 “提交” 一个更新的时候调用这个函数
|
|
|
|
|
|
|
|
|
|
#### onRender 回调函数
|
|
|
|
|
|
|
|
|
|
:- | :-
|
|
|
|
|
:- | :-
|
|
|
|
|
`phase: "mount" \| "update"` | 判断是由 `props`/`state`/`hooks` 改变 或 “第一次装载” 引起的重渲染
|
|
|
|
|
`actualDuration: number` | 本次更新在渲染 Profiler 和它的子代上花费的时间
|
|
|
|
|
`baseDuration: number` | 在 Profiler 树中最近一次每一个组件 render 的持续时间
|
|
|
|
|
`startTime: number` | 本次更新中 React 开始渲染的时间戳
|
|
|
|
|
`commitTime: number` | 本次更新中 React commit 阶段结束的时间戳
|
|
|
|
|
`interactions: Set` | 当更新被制定时,“[interactions](https://fb.me/react-interaction-tracing)” 的集合会被追踪
|
|
|
|
|
|
2022-10-04 00:56:09 +08:00
|
|
|
|
默认值
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
### Class 组件默认 props
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
class CustomButton extends React.Component {
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
CustomButton.defaultProps = {
|
|
|
|
|
color: 'blue'
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 使用
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<CustomButton /> ;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
不传值 `props.color` 将自动设置为 `blue`
|
|
|
|
|
|
|
|
|
|
### Class 组件默认 state
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
class Hello extends Component {
|
|
|
|
|
constructor (props) {
|
|
|
|
|
super(props)
|
|
|
|
|
this.state = { visible: true }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
在构造 `constructor()`中设置默认状态。
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
class Hello extends Component {
|
|
|
|
|
state = { visible: true }
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 函数组件默认 props
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function CustomButton(props) {
|
|
|
|
|
const { color = 'blue' } = props;
|
|
|
|
|
return <div>{color}</div>
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 函数组件默认 state
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function CustomButton() {
|
|
|
|
|
const [color, setColor]=useState('blue')
|
|
|
|
|
return <div>{color}</div>
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
JSX
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
### 介绍
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
`JSX` 仅仅只是 `React.createElement(component, props, ...children)` 函数的语法糖
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<MyButton color="blue" shadowSize={2}>
|
|
|
|
|
点击我
|
|
|
|
|
</MyButton>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
会编译为
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
React.createElement(
|
|
|
|
|
MyButton,
|
|
|
|
|
{color: 'blue', shadowSize: 2},
|
|
|
|
|
'点击我'
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
没有子节点
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<div className="sidebar" />
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
会编译为
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
React.createElement(
|
|
|
|
|
'div',
|
|
|
|
|
{className: 'sidebar'}
|
|
|
|
|
)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### JSX 点语法
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const Menu = ({ children }) => (
|
|
|
|
|
<div className="menu">{children}<div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Menu.Item = ({ children }) => (
|
|
|
|
|
<div>{children}<div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
<Menu>
|
|
|
|
|
<Menu.Item>菜单一</Menu.Item>
|
|
|
|
|
<Menu.Item>菜单二</Menu.Item>
|
|
|
|
|
<Menu>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### JSX Element
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
let element = <h1>Hello, world!</h1>;
|
|
|
|
|
let emptyHeading = <h1 />;
|
|
|
|
|
|
|
|
|
|
const root = ReactDOM.createRoot(
|
|
|
|
|
document.getElementById('root')
|
|
|
|
|
);
|
2022-10-04 11:19:03 +08:00
|
|
|
|
|
2022-10-04 00:56:09 +08:00
|
|
|
|
const element = <h1>Hello, world</h1>;
|
|
|
|
|
root.render(element);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
参考:[渲染元素](https://reactjs.org/docs/rendering-elements.html)
|
|
|
|
|
|
|
|
|
|
### JSX 属性
|
|
|
|
|
|
|
|
|
|
```jsx
|
2022-10-04 11:19:03 +08:00
|
|
|
|
const avatarUrl = "img/picture.jpg"
|
|
|
|
|
const element = <img src={avatarUrl} />;
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
|
|
|
|
const element = (
|
|
|
|
|
<button className="btn">
|
|
|
|
|
点击我
|
|
|
|
|
</button>
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
注意:类属性 `className`
|
|
|
|
|
|
|
|
|
|
### JSX 表达式
|
|
|
|
|
|
|
|
|
|
```jsx
|
2022-10-04 11:19:03 +08:00
|
|
|
|
let name = '张三';
|
2022-10-04 00:56:09 +08:00
|
|
|
|
let element = <h1>Hello, {name}</h1>;
|
|
|
|
|
|
|
|
|
|
function fullName(firstName, lastName) {
|
|
|
|
|
return firstName + ' ' + lastName;
|
|
|
|
|
}
|
|
|
|
|
let element = (
|
|
|
|
|
<h1>
|
2022-10-04 11:19:03 +08:00
|
|
|
|
Hello, {fullName('三', '张')}
|
2022-10-04 00:56:09 +08:00
|
|
|
|
</h1>
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### JSX style
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const divStyle = {
|
|
|
|
|
color: 'blue',
|
|
|
|
|
backgroundImage: 'url(' + imgUrl + ')',
|
|
|
|
|
};
|
|
|
|
|
function MyComponent() {
|
|
|
|
|
return <div style={divStyle}>组件</div>;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### JSX dangerouslySetInnerHTML
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const markup = {__html: '我 · 你' };
|
|
|
|
|
|
|
|
|
|
const MyComponent = () => (
|
|
|
|
|
<div dangerouslySetInnerHTML={markup} />
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`dangerouslySetInnerHTML` 是 React 为浏览器 DOM 提供 `innerHTML` 的替换方案。
|
|
|
|
|
|
|
|
|
|
### JSX htmlFor
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const MyComponent = () => (
|
|
|
|
|
<div>
|
|
|
|
|
<input type="radio" id="ab" name="v">
|
|
|
|
|
<label for="ab">HTML</label>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`for` 在 `JS` 中是保留字,JSX 元素使用了 `htmlFor` 代替
|
|
|
|
|
|
|
|
|
|
### JSX defaultValue
|
|
|
|
|
|
|
|
|
|
非受控组件的属性,设置组件第一次挂载时的 `value`
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<textarea defaultValue="Hello" />
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`<input>`、`<select>` 和 `<textarea>` 支持 value 属性
|
|
|
|
|
|
|
|
|
|
### JSX defaultChecked
|
|
|
|
|
|
|
|
|
|
非受控组件的属性,设置组件是否被选中
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<input type="radio" defaultChecked />
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
类型为 `checkbox` 或 `radio` 时,组件支持 checked 属性
|
|
|
|
|
|
|
|
|
|
### JSX className
|
|
|
|
|
|
|
|
|
|
属性用于指定 `CSS` 的 `class`
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<div className="warp">...</div>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
React 中使用 [Web Components](https://developer.mozilla.org/zh-CN/docs/Web/Web_Components) 使用 `class` 属性代替
|
|
|
|
|
|
|
|
|
|
### JSX 条件渲染
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
import React from "react";
|
|
|
|
|
|
|
|
|
|
function formatName(user) {
|
|
|
|
|
return user.firstName
|
|
|
|
|
+ ' '
|
|
|
|
|
+ user.lastName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function Greeting(user) {
|
|
|
|
|
if (user) {
|
|
|
|
|
return (
|
|
|
|
|
<h1>你好, {formatName(user)}!</h1>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<h1>你好, 先生。</h1>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
注意:组件必须总是返回一些东西。
|
|
|
|
|
|
|
|
|
|
#### 使用
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<Greeting firstName="三" lastName="张" />
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### JSX 三目运算符 / 与运算符 &&
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
export default function Weather(props) {
|
|
|
|
|
const isLoggedIn = props.isLoggedIn;
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<b>{isLoggedIn ? '已' : '未'}</b>登录。
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-11-11 01:51:54 +08:00
|
|
|
|
-----
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
{isShow && <div>内容</div>}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### JSX 组件
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<Dropdown>
|
|
|
|
|
下拉列表
|
|
|
|
|
<Menu>
|
|
|
|
|
<Menu.Item>菜单一</Menu.Item>
|
|
|
|
|
<Menu.Item>菜单二</Menu.Item>
|
|
|
|
|
<Menu.Item>菜单三</Menu.Item>
|
|
|
|
|
</Menu>
|
|
|
|
|
</Dropdown>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
组件名称以大驼峰式命名。
|
|
|
|
|
|
|
|
|
|
### JSX 元素变量
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function Greeting(props) {
|
|
|
|
|
let button;
|
|
|
|
|
if (props.isLoggedIn) {
|
|
|
|
|
button = <UserGreeting />;
|
|
|
|
|
} else {
|
|
|
|
|
button = <GuestGreeting />;
|
|
|
|
|
}
|
|
|
|
|
return <div>{button}</div>;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### JSX 注释
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function Student() {
|
|
|
|
|
const [count, setCount] = useState(0);
|
|
|
|
|
return (
|
|
|
|
|
<Fragment>
|
|
|
|
|
{/* 这里写注释 */}
|
|
|
|
|
</Fragment>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
组件
|
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
### 函数组件
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
import React from 'react';
|
|
|
|
|
|
|
|
|
|
const UserName = () => <h1>Kenny</h1>;
|
|
|
|
|
|
|
|
|
|
export default function UserProfile() {
|
|
|
|
|
return (
|
|
|
|
|
<div className="UserProfile">
|
|
|
|
|
<div>Hello</div>
|
|
|
|
|
<UserName />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
注意:每个组件都需要一个根元素,[更多说明](https://reactjs.org/docs/components-and-props.html)。
|
|
|
|
|
|
|
|
|
|
### Class 组件
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
class Welcome extends React.Component {
|
|
|
|
|
render() {
|
|
|
|
|
return <h1>{this.props.name}</h1>;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Class 组件 API
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
#### 额外的 API
|
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`this.forceUpdate()` | 强制重新渲染
|
|
|
|
|
`this.setState({ ... })` | 更新状态
|
|
|
|
|
`this.setState(state =>{ ... })` | 更新状态
|
|
|
|
|
|
|
|
|
|
#### 属性
|
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`defaultProps` | 默认 props
|
|
|
|
|
`displayName` | 显示组件名称(用于调试)
|
|
|
|
|
|
|
|
|
|
#### 实例属性
|
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`this.props` | 组件接受参数
|
|
|
|
|
`this.state` | 组件内状态
|
|
|
|
|
|
|
|
|
|
### Pure 组件
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
import React, {PureComponent} from 'react'
|
|
|
|
|
|
|
|
|
|
class MessageBox extends PureComponent {
|
|
|
|
|
···
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 高阶组件
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
import React, { Component } from 'react';
|
|
|
|
|
// 高阶组件 with
|
|
|
|
|
const with = data => WrappedComponent => {
|
|
|
|
|
return class extends Component {
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
}
|
|
|
|
|
render() {
|
|
|
|
|
return (
|
|
|
|
|
<WrappedComponent data={data} />
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
使用高阶组件
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const LowComponent = (props) => (
|
|
|
|
|
<div>{props.data}</div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const MyComp = with('Hello')(LowComponent)
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-05 02:43:18 +08:00
|
|
|
|
### 包含关系
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function FancyBorder(props) {
|
|
|
|
|
return (
|
|
|
|
|
<div className={'Fancy'+props.color}>
|
|
|
|
|
{props.children}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
组件可以通过 JSX 嵌套
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function WelcomeDialog() {
|
|
|
|
|
return (
|
|
|
|
|
<FancyBorder color="blue">
|
|
|
|
|
<h1 className="title">欢迎</h1>
|
|
|
|
|
<p className="message">
|
|
|
|
|
感谢您访问我们的宇宙飞船
|
|
|
|
|
</p>
|
|
|
|
|
</FancyBorder>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 作为参数传递
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function SplitPane(props) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="SplitPane">
|
|
|
|
|
<div className="left">
|
|
|
|
|
{props.left}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="right">
|
|
|
|
|
{props.right}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function App() {
|
|
|
|
|
return (
|
|
|
|
|
<SplitPane
|
|
|
|
|
left={<Contacts />}
|
|
|
|
|
right={<Chat />}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
给组件 `SplitPane` 传递 `left` 和 `right` 两个组件参数
|
|
|
|
|
|
|
|
|
|
### 嵌入内部组件
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {2}
|
2022-10-05 02:43:18 +08:00
|
|
|
|
import React from 'react';
|
|
|
|
|
import UserAvatar from "./UserAvatar";
|
|
|
|
|
|
|
|
|
|
export default function UserProfile() {
|
|
|
|
|
return (
|
|
|
|
|
<div className="UserProfile">
|
|
|
|
|
<UserAvatar />
|
|
|
|
|
<UserAvatar />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
注意:假设 `UserAvatar` 在 `UserAvatar.js` 中声明
|
|
|
|
|
|
|
|
|
|
### 嵌入外部组件
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
```jsx {2}
|
2022-10-05 02:43:18 +08:00
|
|
|
|
import React from 'react';
|
|
|
|
|
import {Button} from 'uiw';
|
|
|
|
|
export default function UserProfile() {
|
|
|
|
|
return (
|
|
|
|
|
<div className="UserProfile">
|
|
|
|
|
<Button type="primary">
|
|
|
|
|
主要按钮
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-05 14:46:37 +08:00
|
|
|
|
注意:[uiw](http://npmjs.com/uiw) 组件在 [npmjs.com](https://www.npmjs.com) 上找到,需要先安装导入
|
2022-10-05 02:43:18 +08:00
|
|
|
|
|
2022-10-05 14:52:48 +08:00
|
|
|
|
### 点组件语法技巧
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const Menu = ({ children }) => (
|
|
|
|
|
<div className="menu">{children}<div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Menu.Item = ({ children }) => (
|
|
|
|
|
<div>{children}<div>
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
2022-11-11 01:51:54 +08:00
|
|
|
|
-----
|
2022-10-05 14:52:48 +08:00
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<Menu>
|
|
|
|
|
<Menu.Item>菜单一</Menu.Item>
|
|
|
|
|
<Menu.Item>菜单二</Menu.Item>
|
|
|
|
|
<Menu>
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-06 02:20:53 +08:00
|
|
|
|
Hooks
|
2022-10-04 00:56:09 +08:00
|
|
|
|
---
|
|
|
|
|
|
2022-10-06 02:20:53 +08:00
|
|
|
|
### Hooks API 参考
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
#### 基础 Hook
|
|
|
|
|
|
|
|
|
|
方法 | 描述
|
|
|
|
|
:- | -
|
|
|
|
|
`useState` | 返回一个 `state`,更新 `state` 的函数 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usestate)
|
|
|
|
|
`useEffect` | 可能有副作用代码的函数 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#useeffect)
|
|
|
|
|
`useContext` | 接收并返回该 `context` 的当前值 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usecontext)
|
|
|
|
|
|
|
|
|
|
#### 额外的 Hook
|
|
|
|
|
|
|
|
|
|
方法 | 描述
|
|
|
|
|
:- | -
|
|
|
|
|
`useReducer` | `useState` 的替代方案 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usestate)
|
|
|
|
|
`useCallback` | 返回一个回调函数 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usecallback)
|
|
|
|
|
`useMemo` | 返回一个 [memoized](https://en.wikipedia.org/wiki/Memoization) 值[#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usememo)
|
|
|
|
|
`useRef` | 返回一个可变的 `ref` 对象 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#useref)
|
|
|
|
|
`useImperativeHandle` | 暴露给父组件的实例值 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#useimperativehandle)
|
|
|
|
|
`useLayoutEffect` | DOM 变更后同步调用函数 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#uselayouteffect)
|
|
|
|
|
`useDebugValue` | 开发者工具中显示标签 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usedebugvalue)
|
|
|
|
|
`useDeferredValue` | 接受并返回该值的新副本 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usedeferredvalue)
|
|
|
|
|
`useTransition` | 过渡任务的等待状态 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usetransition)
|
|
|
|
|
`useId` | 用于生成唯一 ID [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#useid)
|
|
|
|
|
|
|
|
|
|
#### Library Hooks
|
|
|
|
|
|
|
|
|
|
方法 | 描述
|
|
|
|
|
:- | -
|
|
|
|
|
`useSyncExternalStore` | 读取和订阅外部数据源 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usesyncexternalstore)
|
|
|
|
|
`useInsertionEffect` | DOM 突变之前 同步触发 [#](https://zh-hans.reactjs.org/docs/hooks-reference.html#usesyncexternalstore)
|
|
|
|
|
|
|
|
|
|
### 函数式更新
|
|
|
|
|
<!--rehype:wrap-class=col-span-2-->
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function Counter({ initialCount }) {
|
|
|
|
|
const [count, setCount] = useState(initialCount);
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
Count: {count} <button onClick={() => setCount(initialCount)}>Reset</button>
|
|
|
|
|
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
|
|
|
|
|
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### useRef
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function TextInputWithFocusButton() {
|
|
|
|
|
const $input = useRef(null);
|
|
|
|
|
const onButtonClick = () => {
|
|
|
|
|
$input.current.focus();
|
|
|
|
|
};
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<input ref={$input} type="text" />
|
|
|
|
|
<button onClick={onButtonClick}>
|
|
|
|
|
聚焦输入
|
|
|
|
|
</button>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`current` 指向已挂载到 DOM 上的文本输入元素
|
|
|
|
|
|
|
|
|
|
### useImperativeHandle
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function FancyInput(props, ref) {
|
|
|
|
|
const inputRef = useRef();
|
|
|
|
|
useImperativeHandle(ref, () => ({
|
|
|
|
|
focus: () => {
|
|
|
|
|
inputRef.current.focus();
|
|
|
|
|
}
|
|
|
|
|
}));
|
|
|
|
|
return <input ref={inputRef} />;
|
|
|
|
|
}
|
|
|
|
|
FancyInput = forwardRef(FancyInput);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
父组件使用
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
<FancyInput ref={inputRef} />
|
|
|
|
|
inputRef.current.focus()
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### useEffect
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const subs = props.source.subscribe();
|
|
|
|
|
return () => {
|
|
|
|
|
subs.unsubscribe();
|
|
|
|
|
};
|
|
|
|
|
}, [props.source]);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### useCallback
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const memoizedCallback = useCallback(
|
|
|
|
|
() => {
|
|
|
|
|
doSomething(a, b);
|
|
|
|
|
},
|
|
|
|
|
[a, b],
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### useMemo
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
const memoizedValue = useMemo(
|
|
|
|
|
() => {
|
|
|
|
|
return computeExpensiveValue(a, b)
|
|
|
|
|
},
|
|
|
|
|
[a, b]
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### useId
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function Checkbox() {
|
|
|
|
|
const id = useId();
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<label htmlFor={id}>
|
|
|
|
|
你喜欢React吗?
|
|
|
|
|
</label>
|
|
|
|
|
<input id={id} type="checkbox" />
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
用于生成跨服务端和客户端稳定的唯一 `ID` 的同时避免 `hydration` 不匹配
|
|
|
|
|
|
|
|
|
|
### useDebugValue
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
function useFriendStatus(friendID) {
|
|
|
|
|
const [
|
|
|
|
|
isOnline, setIsOnline
|
|
|
|
|
] = useState(null);
|
|
|
|
|
// ...
|
|
|
|
|
// 在开发者工具中的这个 Hook 旁边显示标签
|
|
|
|
|
// e.g. "FriendStatus: Online"
|
|
|
|
|
useDebugValue(
|
|
|
|
|
isOnline ? 'Online' : 'Offline'
|
|
|
|
|
);
|
|
|
|
|
return isOnline;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
<!--rehype:className=wrap-text -->
|
|
|
|
|
|
|
|
|
|
不推荐你向每个自定义 `Hook` 添加 `debug` 值
|
|
|
|
|
|
|
|
|
|
### componentDidMount & componentWillUnmount
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
useEffect(
|
|
|
|
|
() => {
|
|
|
|
|
// componentDidMount
|
|
|
|
|
// 组件挂载时,可以在这里完成你的任务
|
|
|
|
|
return () => {
|
|
|
|
|
// componentWillUnmount
|
|
|
|
|
// 卸载时执行,清除 effect
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
[ ]
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
这是一个类似 `class` 组件中 `componentDidMount` & `componentWillUnmount` 两个生命周期函数的写法。
|
|
|
|
|
|
|
|
|
|
生命周期
|
2022-10-04 00:56:09 +08:00
|
|
|
|
---
|
2022-10-06 02:20:53 +08:00
|
|
|
|
<!--rehype:body-class=cols-2-->
|
|
|
|
|
|
|
|
|
|
### 挂载
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
方法 | 描述
|
|
|
|
|
:- | -
|
|
|
|
|
`constructor` _(props)_ | 渲染前 [#](https://zh-hans.reactjs.org/docs/react-component.html#constructor)
|
|
|
|
|
`static getDerivedStateFromProps()` | 调用 `render` 方法之前调用 [#](https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromprops)
|
|
|
|
|
`render()` | `class` 组件中唯一必须实现的方法 [#](https://reactjs.org/docs/react-component.html#render)
|
|
|
|
|
`componentDidMount()` | 在组件挂载后(插入 DOM 树中)立即调用 [#](https://reactjs.org/docs/react-component.html#componentdidmount)
|
|
|
|
|
`UNSAFE_componentWillMount()` | 在挂载之前被调用,建议使用 `constructor()` [#](https://zh-hans.reactjs.org/docs/react-component.html#unsafe_componentwillmount)
|
|
|
|
|
|
|
|
|
|
在 `constructor()` 上设置初始状态。在 `componentDidMount()` 上添加 DOM 事件处理程序、计时器(等),然后在 `componentWillUnmount()` 上删除它们。
|
|
|
|
|
|
|
|
|
|
### 卸载
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
2022-10-06 02:20:53 +08:00
|
|
|
|
方法 | 描述
|
|
|
|
|
:- | -
|
|
|
|
|
`componentWillUnmount()` | 在组件卸载及销毁之前直接调用 [#](https://zh-hans.reactjs.org/docs/react-component.html#componentwillunmount)
|
|
|
|
|
|
|
|
|
|
### 过时 API
|
|
|
|
|
|
|
|
|
|
过时方法 | 新方法
|
|
|
|
|
:- | -
|
|
|
|
|
~~`componentWillMount()`~~ | `UNSAFE_componentWillMount()` [#](https://zh-hans.reactjs.org/docs/react-component.html#unsafe_componentwillmount)
|
|
|
|
|
~~`componentWillReceiveProps()`~~ | `UNSAFE_componentWillReceiveProps()` [#](https://zh-hans.reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops)
|
|
|
|
|
~~`componentWillUpdate()`~~ | `UNSAFE_componentWillUpdate()` [#](https://zh-hans.reactjs.org/docs/react-component.html#unsafe_componentwillupdate)
|
|
|
|
|
|
|
|
|
|
17+ 之后不再支持,在 `17` 版本之后,只有新的 `UNSAFE_` 生命周期名称可以使用。
|
|
|
|
|
|
|
|
|
|
### 更新
|
|
|
|
|
<!--rehype:wrap-class=col-span-2-->
|
|
|
|
|
|
|
|
|
|
方法 | 描述
|
|
|
|
|
:- | -
|
|
|
|
|
`static getDerivedStateFromProps(props, state)` | 调用 `render` 之前调用,在初始挂载及后续更新时都会被调用 [#](https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromprops)
|
|
|
|
|
`shouldComponentUpdate(nextProps, nextState)` | 如果返回 `false`,则跳过 `render()` [#](https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromprops)
|
|
|
|
|
`render()` | 在不修改组件 `state` 的情况下,每次调用时都返回相同的结果 [#](https://zh-hans.reactjs.org/docs/react-component.html#render)
|
|
|
|
|
`getSnapshotBeforeUpdate()` | 在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置) [#](https://zh-hans.reactjs.org/docs/react-component.html#getsnapshotbeforeupdate)
|
|
|
|
|
`componentDidUpdate()` | 这里使用 `setState()`,但记得比较 `props`。首次渲染不会执行此方法 [#](https://zh-hans.reactjs.org/docs/react-component.html#componentdidupdate)
|
|
|
|
|
|
|
|
|
|
### 错误处理
|
|
|
|
|
<!--rehype:wrap-class=col-span-2-->
|
|
|
|
|
|
|
|
|
|
方法 | 描述
|
|
|
|
|
:- | -
|
|
|
|
|
`static getDerivedStateFromError(error)` | 后代组件抛出错误后被调用,它将抛出的错误作为参数,并返回一个值以更新 `state` [#](https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromerror)
|
|
|
|
|
`componentDidCatch(error, info)` | 在后代组件抛出错误后被调用,会在“提交”阶段被调用,因此允许执行副作用 [#](https://zh-hans.reactjs.org/docs/react-component.html#componentdidcatch)
|
|
|
|
|
|
|
|
|
|
### render()
|
|
|
|
|
|
|
|
|
|
```jsx {2}
|
|
|
|
|
class Welcome extends React.Component {
|
|
|
|
|
render() {
|
|
|
|
|
return <h1>Hello, {this.props.name}</h1>;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### constructor()
|
|
|
|
|
|
|
|
|
|
```jsx {1}
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
// 不要在这里调用 this.setState()
|
|
|
|
|
this.state = { counter: 0 };
|
|
|
|
|
this.handleClick = this.handleClick.bind(this);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### static getDerivedStateFromError()
|
|
|
|
|
<!--rehype:wrap-class=row-span-2-->
|
|
|
|
|
|
|
|
|
|
```jsx {7,13}
|
|
|
|
|
class ErrorBoundary extends React.Component {
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = { hasError: false };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static getDerivedStateFromError(error) {
|
|
|
|
|
// 更新 state 使下一次渲染可以显降级 UI
|
|
|
|
|
return { hasError: true };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
|
if (this.state.hasError) {
|
|
|
|
|
// 你可以渲染任何自定义的降级 UI
|
|
|
|
|
return <h1>Something went wrong.</h1>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this.props.children;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### componentDidUpdate()
|
|
|
|
|
|
|
|
|
|
```jsx {1}
|
|
|
|
|
componentDidUpdate(prevProps) {
|
|
|
|
|
// 典型用法(不要忘记比较 props):
|
|
|
|
|
if (this.props.uid !== prevProps.uid) {
|
|
|
|
|
this.fetchData(this.props.uid);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### getSnapshotBeforeUpdate()
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
getSnapshotBeforeUpdate(prevProps, prevState) {
|
|
|
|
|
// 我们是否在 list 中添加新的 items ?
|
|
|
|
|
// 捕获滚动位置以便我们稍后调整滚动位置。
|
|
|
|
|
if (prevProps.list.length < this.props.list.length) {
|
|
|
|
|
const list = this.listRef.current;
|
|
|
|
|
return list.scrollHeight - list.scrollTop;
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
```
|
2022-10-04 00:56:09 +08:00
|
|
|
|
|
2022-10-05 01:34:11 +08:00
|
|
|
|
PropTypes 属性类型检查
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
### PropTypes
|
|
|
|
|
<!--rehype:wrap-class=row-span-3-->
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
import PropTypes from 'prop-types'
|
|
|
|
|
```
|
|
|
|
|
|
2022-11-11 01:51:54 +08:00
|
|
|
|
-----
|
2022-10-05 01:34:11 +08:00
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`any` | 任意类型
|
|
|
|
|
`(props, propName, 组件名称)=>{}` | 自定义验证器
|
|
|
|
|
|
2022-10-05 02:51:57 +08:00
|
|
|
|
#### _基础_
|
2022-10-05 01:34:11 +08:00
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`string` | 字符串
|
|
|
|
|
`number` | 数组
|
|
|
|
|
`func` | 函数
|
|
|
|
|
`bool` | 布尔值
|
|
|
|
|
`symbol` | -
|
|
|
|
|
|
2022-10-05 02:51:57 +08:00
|
|
|
|
#### _枚举 Enum_
|
2022-10-05 01:34:11 +08:00
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`oneOf(any)` | 枚举类型
|
|
|
|
|
`oneOfType([type])` | 几种类型中的任意一个类型
|
|
|
|
|
|
2022-10-05 02:51:57 +08:00
|
|
|
|
#### _数组 Array_
|
2022-10-05 01:34:11 +08:00
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`array` | 数组
|
|
|
|
|
`arrayOf` | 数组由某一类型的元素组成
|
|
|
|
|
|
2022-10-05 02:51:57 +08:00
|
|
|
|
#### _对象 Object_
|
2022-10-05 01:34:11 +08:00
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`object` | 对象
|
|
|
|
|
`objectOf` | 对象由某一类型的值组成
|
|
|
|
|
`instanceOf(...)` | 类的实例
|
|
|
|
|
`shape` | 对象由特定的类型值组成
|
|
|
|
|
`exact` | 有额外属性警告
|
|
|
|
|
|
2022-10-05 02:51:57 +08:00
|
|
|
|
#### _元素 Elements_
|
2022-10-05 01:34:11 +08:00
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`element` | React 元素
|
|
|
|
|
`elementType` | React 元素类型(即 `MyComponent`)
|
|
|
|
|
`node` | DOM 节点
|
|
|
|
|
|
2022-10-05 02:51:57 +08:00
|
|
|
|
#### _必需的_
|
2022-10-05 01:34:11 +08:00
|
|
|
|
|
|
|
|
|
:- | -
|
|
|
|
|
:- | -
|
|
|
|
|
`(···).isRequired` | 必需的
|
|
|
|
|
|
|
|
|
|
请参阅:[使用 PropTypes 进行类型检查](https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html)
|
|
|
|
|
|
|
|
|
|
### 基本类型
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
email: PropTypes.string,
|
|
|
|
|
seats: PropTypes.number,
|
|
|
|
|
callback: PropTypes.func,
|
|
|
|
|
isClosed: PropTypes.bool,
|
|
|
|
|
any: PropTypes.any
|
|
|
|
|
symbol: PropTypes.symbol,
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
你可以将属性声明为 JS 原生类型,默认都是可选的。
|
|
|
|
|
|
|
|
|
|
### 必需的
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
// 确保这个 prop 没有被提供时,会打印警告信息
|
|
|
|
|
requiredFunc: PropTypes.func.isRequired,
|
|
|
|
|
|
|
|
|
|
// 任意类型的必需数据
|
|
|
|
|
requiredAny: PropTypes.any.isRequired,
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
你可以在任何 `PropTypes` 属性后面加上 `isRequired`。
|
|
|
|
|
|
|
|
|
|
### 枚举
|
|
|
|
|
|
|
|
|
|
```js
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
// 只能是特定的值,枚举类型。
|
|
|
|
|
optionalEnum: PropTypes.oneOf([
|
|
|
|
|
'News', 'Photos'
|
|
|
|
|
]),
|
|
|
|
|
// 一个对象可以是几种类型中的任意一个类型
|
|
|
|
|
optionalUnion: PropTypes.oneOfType([
|
|
|
|
|
PropTypes.string,
|
|
|
|
|
PropTypes.number,
|
|
|
|
|
PropTypes.instanceOf(Message)
|
|
|
|
|
]),
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 元素 Elements
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
// 任何可被渲染的元素
|
|
|
|
|
// (包括数字、字符串、元素或数组)
|
|
|
|
|
// (或 Fragment) 也包含这些类型。
|
|
|
|
|
node: PropTypes.node,
|
|
|
|
|
|
|
|
|
|
// 一个 React 元素。
|
|
|
|
|
element: PropTypes.element,
|
|
|
|
|
|
|
|
|
|
// 一个 React 元素类型(即,MyComponent)
|
|
|
|
|
elementType: PropTypes.elementType,
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 对象 Object
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
// 可以指定一个对象由某一类型的值组成
|
|
|
|
|
objectOf: PropTypes.objectOf(
|
|
|
|
|
PropTypes.number
|
|
|
|
|
),
|
|
|
|
|
// 可以指定一个对象由特定的类型值组成
|
|
|
|
|
objectWithShape: PropTypes.shape({
|
|
|
|
|
color: PropTypes.string,
|
|
|
|
|
fontSize: PropTypes.number
|
|
|
|
|
}),
|
|
|
|
|
// 带有额外属性警告的对象
|
|
|
|
|
objectWithStrictShape: PropTypes.exact({
|
|
|
|
|
name: PropTypes.string,
|
|
|
|
|
quantity: PropTypes.number
|
|
|
|
|
}),
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 自定义验证器
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
custom: (props, propName, compName) => {
|
|
|
|
|
if (!/matchm/.test(props[propName])) {
|
|
|
|
|
// 它在验证失败时应返回一个 Error 对象
|
|
|
|
|
return new Error(
|
|
|
|
|
'无效的prop `'
|
|
|
|
|
` \`${propName}\` 提供给` +
|
|
|
|
|
` \`${compName}\`。验证失败。`
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
请不要使用 `console.warn` 或抛出异常,因为这在 `oneOfType` 中不会起作用。
|
|
|
|
|
|
|
|
|
|
### 自定义的 `arrayOf` 或 `objectOf` 验证器
|
|
|
|
|
<!--rehype:wrap-class=col-span-2 row-span-2-->
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
arrayProp: PropTypes.arrayOf((propValue, key, componentName, location, propFullName) => {
|
|
|
|
|
if (!/matchme/.test(propValue[key])) {
|
|
|
|
|
// 它应该在验证失败时返回一个 Error 对象。
|
|
|
|
|
return new Error(
|
|
|
|
|
'Invalid prop `' + propFullName + '` supplied to' +
|
|
|
|
|
' `' + componentName + '`. Validation failed.'
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`propValue` 是数组或对象本身,`key` 是他们当前的键。
|
|
|
|
|
|
|
|
|
|
### 数组
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
arr: PropTypes.arrayOf(PropTypes.number),
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
可以指定一个数组由某一类型的元素组成
|
|
|
|
|
|
|
|
|
|
### 验证类的实例
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
MyComponent.propTypes = {
|
|
|
|
|
message: PropTypes.instanceOf(Message),
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
2022-10-05 02:43:18 +08:00
|
|
|
|
声明 `message` 为类的实例
|
|
|
|
|
|
2022-10-04 00:56:09 +08:00
|
|
|
|
另见
|
|
|
|
|
----
|
|
|
|
|
|
2022-10-04 00:59:54 +08:00
|
|
|
|
- [React 官方中文文档](https://zh-hans.reactjs.org/) _(zh-hans.reactjs.org)_
|
|
|
|
|
- [反应生命周期方法图](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/) _(projects.wojtekmaj.pl)_
|
|
|
|
|
- [React 16 Cheat Sheet](https://reactcheatsheet.com)
|
2022-11-11 01:51:54 +08:00
|
|
|
|
- [Awesome React](https://github.com/enaqx/awesome-react) _(github.com)_
|