React 是一个用于构建用户界面的 JavaScript 库
import {createRoot} from 'react-dom/client'
import App from './App'
const elm = document.getElementById('app')
const root = createRoot(elm);
root.render(<App />);
npx create-react-app my-app
function Example() {
return (
<AlertBox>
<h1>您有待处理的通知</h1>
</AlertBox>
)
}
函数 AlertBox 组件
function AlertBox(props) {
return (
<div className="alert-box">
{props.children}
</div>
);
}
{props.children}
Class AlertBox 组件,与函数组件 AlertBox 组件相同
class AlertBox extends React.Component {
render () {
return (
<div className="alert-box">
{this.props.children}
</div>
);
}
}
{this.props.children}
children 作为子组件的的属性传递。
函数中的 State,Hook 是 React 16.8 的新增特性
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 更新状态,下面是函数组件读取状态
<p>您点击了 {count} 次</p>
import React from 'react';
class Student extends React.Component {
constructor(props) {
super(props);
this.state = {count: 1};
// 确保函数可以访问组件属性(ES2015)
this.click = this.click.bind(this);
}
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 组件中不能使用 hooksclass 组件读取状态
<p>您点击了{this.state.count}次</p>
import { Fragment } from 'react'
import Avatar from './Avatar';
import Profile from './Profile';
const Student = () => (
<Fragment>
<Avatar src="./demo.jpg" />
<Profile username="name" />
</Fragment>
);
从 v16.2.0 开始 Fragment 可用于返回多个子节点,而无需向 DOM 添加额外的包装节点。或者使用 <></> 效果是一样的。
const Student = () => (
<>
<Avatar src="./demo.jpg" />
<Profile username="name" />
</>
);
render() {
return 'Look ma, no spans!';
}
您可以只返回一个字符串。查看: Fragments & strings
const Student = () => [
<li key="A">First item</li>,
<li key="B">Second item</li>
];
不要忘记 key!查看: Fragments & strings
import {Component,createRef} from 'react'
class MyComponent extends Component {
constructor(props) {
super(props);
this.myRef = createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
提示:Refs 适用于类组件,但不适用于函数组件(除非您使用 useRef hook,请参阅hooks)
<div>
<Header />
<React.StrictMode>
<div>
<ComponentOne />
<ComponentTwo />
</div>
</React.StrictMode>
<Footer />
</div>
突出显示应用程序中潜在问题的工具。请参阅:严格模式
测量一个 React 应用多久渲染一次以及渲染一次的 代价
<Profiler id="Navigation" onRender={callback}>
<Navigation {...props} />
</Profiler>
为了分析 Navigation 组件和它的子代。应该在需要时才去使用它。
| :- | :- |
|---|---|
id(string) | 发生提交的 Profiler 树的 id |
onRender(function) | 组件树任何组件 “提交” 一个更新的时候调用这个函数 |
| :- | :- |
|---|---|
phase: "mount" | "update" | 判断是由 props/state/hooks 改变 或 “第一次装载” 引起的重渲染 |
actualDuration: number | 本次更新在渲染 Profiler 和它的子代上花费的时间 |
baseDuration: number | 在 Profiler 树中最近一次每一个组件 render 的持续时间 |
startTime: number | 本次更新中 React 开始渲染的时间戳 |
commitTime: number | 本次更新中 React commit 阶段结束的时间戳 |
interactions: Set | 当更新被制定时,“interactions” 的集合会被追踪 |
props 被传递给组件并且是不可变的。State 是组件的本地状态,可以更改。function ChildComponent({ name }) {
return <h2>Hi,my name is {name}.</h2>;
}
function ParentComponent() {
// State to manage the name value
const [name, setName]= usestate('John');
const changeName = () => {
setName('Jane');
};
return (
<div>
<ChildComponent name={name}/>
<button onClick={changeName}>
Change Names
</button>
</div>
);
}
let element = <h1>Hello, world!</h1>;
let emptyHeading = <h1 />;
const root = ReactDOM.createRoot(
document.getElementById('root')
);
const element = <h1>Hello, world</h1>;
root.render(element);
参考:渲染元素
import React from 'react';
const UserName = () => <h1>Kenny</h1>;
export default function UserProfile() {
return (
<div className="UserProfile">
<div>Hello</div>
<UserName />
</div>
);
}
注意:每个组件都需要一个根元素,更多说明。
import React, { Component } from 'react';
// 高阶组件 with
const with = data => WrappedComponent => {
return class extends Component {
constructor(props) {
super(props);
}
render() {
return (
<WrappedComponent data={data} />
)
}
}
}
使用高阶组件
const LowComponent = (props) => (
<div>{props.data}</div>
);
const MyComp = with('Hello')(LowComponent)
| 方法 | 描述 |
|---|---|
useState | 返回一个 state,更新 state 的函数 # |
useEffect | 可能有副作用代码的函数 # |
useContext | 接收并返回该 context 的当前值 # |
| 方法 | 描述 |
|---|---|
useReducer | useState 的替代方案 # |
useCallback | 返回一个回调函数 # |
useMemo | 返回一个 memoized 值# |
useRef | 返回一个可变的 ref 对象 # |
useImperativeHandle | 暴露给父组件的实例值 # |
useLayoutEffect | DOM 变更后同步调用函数 # |
useDebugValue | 开发者工具中显示标签 # |
useDeferredValue | 接受并返回该值的新副本 # |
useTransition | 过渡任务的等待状态 # |
useId | 用于生成唯一 ID # |
| 方法 | 描述 |
|---|---|
useSyncExternalStore | 读取和订阅外部数据源 # |
useInsertionEffect | DOM 突变之前 同步触发 # |
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>
</>
);
}
| 方法 | 描述 |
|---|---|
constructor (props) | 渲染前 # |
static getDerivedStateFromProps() | 调用 render 方法之前调用 # |
render() | class 组件中唯一必须实现的方法 # |
componentDidMount() | 在组件挂载后(插入 DOM 树中)立即调用 # |
UNSAFE_componentWillMount() | 在挂载之前被调用,建议使用 constructor() # |
在 constructor() 上设置初始状态。在 componentDidMount() 上添加 DOM 事件处理程序、计时器(等),然后在 componentWillUnmount() 上删除它们。
| 方法 | 描述 |
|---|---|
componentWillUnmount() | 在组件卸载及销毁之前直接调用 # |
| 方法 | 描述 |
|---|---|
static getDerivedStateFromProps(props, state) | 调用 render 之前调用,在初始挂载及后续更新时都会被调用 # |
shouldComponentUpdate(nextProps, nextState) | 如果返回 false,则跳过 render() # |
render() | 在不修改组件 state 的情况下,每次调用时都返回相同的结果 # |
getSnapshotBeforeUpdate() | 在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置) # |
componentDidUpdate() | 这里使用 setState(),但记得比较 props。首次渲染不会执行此方法 # |
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;
}
}
import PropTypes from 'prop-types'
| :- | - |
|---|---|
any | 任意类型 |
(props, propName, 组件名称)=>{} | 自定义验证器 |
| :- | - |
|---|---|
string | 字符串 |
number | 数组 |
func | 函数 |
bool | 布尔值 |
symbol | - |
| :- | - |
|---|---|
oneOf(any) | 枚举类型 |
oneOfType([type]) | 几种类型中的任意一个类型 |
| :- | - |
|---|---|
array | 数组 |
arrayOf | 数组由某一类型的元素组成 |
| :- | - |
|---|---|
object | 对象 |
objectOf | 对象由某一类型的值组成 |
instanceOf(...) | 类的实例 |
shape | 对象由特定的类型值组成 |
exact | 有额外属性警告 |
| :- | - |
|---|---|
element | React 元素 |
elementType | React 元素类型(即 MyComponent) |
node | DOM 节点 |
| :- | - |
|---|---|
(···).isRequired | 必需的 |
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
}),
}
arrayOf 或 objectOf 验证器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 是他们当前的键。