React 中组件的生命周期
官方生命周期速查表
官方生命周期速查表
注意:速查表上方有个是否显示不常用的生命周期以及react版本和国际化;
类(class)组件生命周期
每个类组件都包含"生命周期方法",实质上是钩子函数,通过重写这些钩子函数,可以帮助我们在特定的契机执行一些动作。
这里记录一下常用的和不常用的生命周期方法,即将过时和过时的生命周期方法不做记录;
注意: React version ≥ 16.4;
import React from 'react';
class Cycle extends React.Component {
// React 组件挂载之前调用
constructor(props) {
// 必须调用 super(props), 否则在构造函数中无法使用 this.props
super(props);
// 在 constructor 中,以这种形式初始化 state
this.state = {
name: "赵云"
}
}
// 组件挂在之后(插入DOM树中)调用, 此时dom已渲染
componentDidMount() {
/**
* 可以添加一些依赖于 DOM 节点的初始化操作
* 1. 网络请求获取数据
* 2. 添加订阅
* 注意:在此调用 setState(), 将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前,
* 即使两次调用 render() 用户也不会开到中间状态,值得注意的是这种操作会导致性能问题,
* 谨慎使用。
*/
console.log("componentDidMount");
}
// 组件更新后调用
componentDidUpdate(prevProps, prevState, snapshot) {
/**
* 如果组件实现了 getSnapshotBeforeUpdate() 生命周期(不常用),则它的返回值将作为
* componentDidUpdate() 的第三个参数 “snapshot” 参数传递。否则此参数将为 undefined。
*
* 注意:如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate();
*/
console.log("componentDidUpdate");
}
// 组件卸载及销毁之前调用
componentWillUnmount() {
/**
* 可以添加一些必要的清除操作操作
* 1. 清除 timer
* 2. 取消订阅
* 3. 取消网络请求
* 注意:这里不应该调用 setState() ,因为组件将永远不会重新渲染
*/
console.log("componentWillUnmount");
}
// class 组件中唯一必须实现的方法
render() {
// 一个纯渲染函数,返回Dom,React组件,Fragment等
return null;
}
// 通过返回值(true/false)判断是否重新渲染(执行render())
shouldComponentUpdate(nextProps, nextState) {
/**
* 当 props 或 state 发生变化时,会在渲染执行之前被调用,返回 true
* 则重新渲染,返回 false, 则不渲染,默认返回 true;
* 1. 性能优化: 根据nextProps, nextState判断是否重新渲染,减少渲染次数;
*
* 注意:首次渲染或使用 forceUpdate() 时不会调用;
*/
console.log("shouldComponentUpdate");
}
// 调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用
static getDerivedStateFromProps(nextProps, prevState) {
// 通过接受父组件props判断是否执行更新,返回null不更新
console.log("getDerivedStateFromProps");
}
// 最近一次渲染输出(提交到 DOM 节点)之前调用
getSnapshotBeforeUpdate(prevProps, prevState) {
// 判断dom节点更新阶段更新时,及时获取更新后的dom节点
console.log("getSnapshotBeforeUpdate");
}
// 在后代组件抛出错误后被调用
static getDerivedStateFromError(error) {
console.log("getDerivedStateFromError");
}
// 在后代组件抛出错误后被调用
componentDidCatch(error, info) {
console.log("componentDidCatch");
}
}
export default Cycle;
在实际开发中,比较常用的生命周期方法有:
render()
, constructor()
, componentDidMount()
, componentDidUpdate
, componentWillUnmount()
;
不常用的生命周期方法有:shouldComponentUpdate()
, static getDerivedStateFromProps()
, getSnapshotBeforeUpdate()
, static getDerivedStateFromError()
, componentDidCatch()
;
还有一些过时的就不列举了,过时的在开发以不推荐使用,后续版本会淘汰掉,能不用就不要用;
hooks 组件的钩子函数
import React from 'react';
const Hooks = (props) => {
// useState 与类组件的state类似
const [name, setName] = React.useState("name");
// React.useMemo 组件Dom节点,进行计算一些包括要渲染的Dom或者数据,根据依赖参数进行更新
React.useMemo(() => {
console.log("组件DOM节点没有渲染之前调用一次");
}, []);
const renderDom = React.useMemo(() => {
return () => {
console.log("组件DOM节点没有渲染之前根据依赖参数props调用");
}
}, [props]);
// React.useEffect hooks的组件生命周期其实就是钩子函数useEffect的不同用法,
// 传递参数的不同会导致不同的结果
React.useEffect(() => {
console.log("组件初始化调用一次");
}, []);
React.useEffect(() => {
console.log("组件根据依赖参数props更新调用");
}, [props]);
React.useEffect(() => {
return () => {
console.log("组件卸载调用");
}
}, []);
// React.useCallback 一个钩子函数,通过包裹我们的普通函数进行性能优化
const handleClick = React.useCallback(() => {
console.log("监听事件通过钩子函数包裹,优化性能");
}, []);
// 返回 DOM节点
return <div>hooks</div>;
}
export default Hooks;