类组件
React 有2种定义组件的方式,一种是使用函数声明的方式,即函数组件;另一种是使用 ES6 类语法来定义组件的方式,即类组件。
如果组件需要使用继承或生命周期,那么使用类组件,否则使用函数组件。
继承
类组件一般继承自 React.Component,也可以继承自 React.PureComponent,后者是前者的扩展,它内置了对 shouldComponentUpdate() 方法的浅比较,从而减少不必要的重新渲染。
需要注意的是,浅比较只比较了属性和状态的引用,如果属性或状态是复杂的对象或数组,而其内部值发生变化,浅比较可能会出现误判。
类组件允许子组件继承父组件的属性、方法和状态,实现代码的复用。
生命周期
组件创建顺序
- constructor(props):初始化组件的状态和属性
- static getDerivedStateFromProps(props, state):返回一个对象更新状态,或者返回 null 不更新状态
- render:渲染组件的内容
- componentDidMount():在组件挂载到 DOM 后调用
组件更新顺序
- static getDerivedStateFromProps(props, state):同上
- shouldComponetUpdate(nextPrps,nextState):决定是否重新渲染组件,可以通过返回 false 来阻止不必要的渲染
- render:渲染组件的内容
- getSnapshotBeforeUpdate(prevProps, prevState):让组件在 DOM 可能发生变化之前捕捉到一些信息(如滚动位置),将返回值作为第三个参数传递给 componentDidUpdate()
- componentDidUpdate(prevProps, prevState):在组件更新后调用
组件卸载顺序
- 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 的第二个参数,它接受一个回调函数,在状态更新完毕后调用。
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种绑定事件的方法
- 使用 bind 显式绑定,确保 this 指向组件实例
class MyApp extends React.Componenet {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
// ...
}
}
- 使用箭头函数,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'
};