Skip to main content

类组件

React 有2种定义组件的方式,一种是使用函数声明的方式,即函数组件;另一种是使用 ES6 类语法来定义组件的方式,即类组件。

如果组件需要使用继承或生命周期,那么使用类组件,否则使用函数组件。

继承

类组件一般继承自 React.Component,也可以继承自 React.PureComponent,后者是前者的扩展,它内置了对 shouldComponentUpdate() 方法的浅比较,从而减少不必要的重新渲染。

需要注意的是,浅比较只比较了属性和状态的引用,如果属性或状态是复杂的对象或数组,而其内部值发生变化,浅比较可能会出现误判。

类组件允许子组件继承父组件的属性、方法和状态,实现代码的复用。

生命周期

组件创建顺序

  1. constructor(props):初始化组件的状态和属性
  2. static getDerivedStateFromProps(props, state):返回一个对象更新状态,或者返回 null 不更新状态
  3. render:渲染组件的内容
  4. componentDidMount():在组件挂载到 DOM 后调用

组件更新顺序

  1. static getDerivedStateFromProps(props, state):同上
  2. shouldComponetUpdate(nextPrps,nextState):决定是否重新渲染组件,可以通过返回 false 来阻止不必要的渲染
  3. render:渲染组件的内容
  4. getSnapshotBeforeUpdate(prevProps, prevState):让组件在 DOM 可能发生变化之前捕捉到一些信息(如滚动位置),将返回值作为第三个参数传递给 componentDidUpdate()
  5. componentDidUpdate(prevProps, prevState):在组件更新后调用

组件卸载顺序

  1. componetWillUnmount():在组件即将被卸载前调用

错误处理

  • static getDerivedStateFromError(error):在后代组件出错后被调用,它接收抛出的错误作为参数,并返回一个值来更新状态
  • componentDidCatch(error, info):在后代组件抛出错误后被调用

已不推荐使用

  • UNSAFE_componentWillReceiveProps(nextProps):当父组件重新渲染,并且传递给子组件的属性发生变化时调用

    • 顺序在 getDerivedStateFromProps() 之后
  • UNSAFE_componentWillMount():在组件即将被挂载到 DOM 前调用

    • 顺序在 constructor() 之后
  • UNSAFE_componentWillUpdate(nextProps, nextState):在组件即将重新渲染前调用

    • 顺序在 shouldComponetUpdate() 之后

this.setState

this.setState 是 React 类组件中用于更新组件状态的方法,它是异步的,这意味着状态更新不会立即生效,React 会将多次状态更新合并成一个更新操作,以提高性能。

如果需要在状态更新后执行某些操作,可以使用 this.setState 的第二个参数,它接受一个回调函数,在状态更新完毕后调用。

index.tsx
import React from 'react';

class MyApp extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}

incrementCount() {
// 使用 this.setState 更新状态
this.setState({ count: this.state.count + 1 }, () => {
console.log('State updated:', this.state.count);
});
}

render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={() => this.incrementCount()}>Increment</button>
</div>
);
}
};

export default MyApp;

防止不必要的更新

getUserProfile = user => {
const latestAddress = user.address;
this.setState(state => {
if (state.address === latestAddress) {
return null;
} else {
return { title: latestAddress };
}
});
};

事件处理

在类组件中,有2种绑定事件的方法

  1. 使用 bind 显式绑定,确保 this 指向组件实例
class MyApp extends React.Componenet {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}

handleClick() {
// ...
}
}
  1. 使用箭头函数,this 会指向当前词法作用域

组件每次渲染时,在 render 方法中的箭头函数都会创建一个新的函数,这可能会影响性能。

handleClick = () => {
console.log('this is:', this)
}

super

如果需要访问 this.props,需要将 props 传递给 super() 方法。

class MyApp extends React.Component {
constructor(props) {
super(props)
console.log(this.props) // { name: 'Alice', ... }
}
}
class MyApp extends React.Component {
constructor(props) {
super()
console.log(this.props) // undefined
}
}

定义静态属性

class MyApp extends React.Component {
static PAI = 3.1415
}

设置默认属性

defaultProps 被定义为组件类上的属性,用于设置组件类默认的属性值。

class MyApp extends React.Component {
// ...
};

MyApp.defaultProps = {
color: 'red'
};