MST

星途 面试题库

面试题:React 新老生命周期更替对性能调优策略的影响及实践

React 从旧的生命周期(如 `componentWillMount` 等)过渡到新的生命周期(如 `getDerivedStateFromProps` 等),这一变化对性能调优策略带来了哪些具体影响?在实际项目中,如何基于新的生命周期实现更高效的性能优化?请结合具体的代码示例进行说明。
15.5万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

1. 旧生命周期到新生命周期变化对性能调优策略的影响

  • 避免在 componentWillMount 中发起异步操作:在旧生命周期中,componentWillMount 常用于发起异步请求,但由于该方法可能在服务器端渲染(SSR)和客户端渲染时被调用两次,可能导致数据重复获取。新生命周期移除了 componentWillMount,推荐在 componentDidMount 中发起异步操作,这确保只在客户端渲染时执行一次,提升性能。
  • componentWillReceiveProps 的改变:旧的 componentWillReceiveProps 容易导致不必要的 state 更新,因为只要父组件重新渲染,无论 props 是否变化,该方法都会被调用。新的 getDerivedStateFromProps 则要求根据 props 和当前 state 决定是否更新 state,使得 state 更新更可控,减少不必要的渲染。
  • shouldComponentUpdate 逻辑更重要:新生命周期强调通过 shouldComponentUpdate 来精准控制组件更新。由于 getDerivedStateFromProps 只负责根据 props 更新 state,而 shouldComponentUpdate 决定组件是否真的需要更新,合理编写此方法可避免大量不必要的渲染。

2. 基于新生命周期实现高效性能优化的方法及示例

使用 getDerivedStateFromProps

import React, { Component } from 'react';

class Counter extends Component {
    constructor(props) {
        super(props);
        this.state = {
            count: props.initialCount
        };
    }

    static getDerivedStateFromProps(nextProps, prevState) {
        if (nextProps.initialCount!== prevState.count) {
            return {
                count: nextProps.initialCount
            };
        }
        return null;
    }

    render() {
        return <div>{this.state.count}</div>;
    }
}

在此示例中,getDerivedStateFromProps 确保只有当 props 中的 initialCount 变化时,state 中的 count 才会更新,避免了不必要的 state 更新,从而减少可能的重新渲染。

合理使用 shouldComponentUpdate

import React, { Component } from 'react';

class ListItem extends Component {
    shouldComponentUpdate(nextProps, nextState) {
        return nextProps.item!== this.props.item;
    }

    render() {
        return <li>{this.props.item}</li>;
    }
}

在这个 ListItem 组件中,shouldComponentUpdate 方法检查 props 中的 item 是否变化。只有当 item 变化时,组件才会重新渲染,避免了因父组件其他无关变化导致的不必要渲染,提升了性能。

componentDidMount 中处理副作用

import React, { Component } from 'react';

class DataFetcher extends Component {
    constructor(props) {
        super(props);
        this.state = {
            data: null
        };
    }

    componentDidMount() {
        fetch('https://example.com/api/data')
          .then(response => response.json())
          .then(data => this.setState({ data }));
    }

    render() {
        if (!this.state.data) {
            return <div>Loading...</div>;
        }
        return <div>{JSON.stringify(this.state.data)}</div>;
    }
}

这里将数据获取操作放在 componentDidMount 中,确保只在客户端渲染后执行一次,避免了旧生命周期中 componentWillMount 可能带来的重复数据获取问题,优化了性能。