MST

星途 面试题库

面试题:React高阶组件封装生命周期逻辑在复杂业务场景下的优化与实践

假设你正在开发一个大型的React应用,其中多个组件需要复用一些复杂的生命周期逻辑,例如在组件挂载时发起多个异步请求,并在数据返回后根据不同的条件渲染不同的内容,同时在组件更新时需要处理不同类型的props变化并进行相应的操作。请说明如何利用高阶组件封装这些复杂的生命周期逻辑,以提高代码的可维护性和复用性,并阐述在实践过程中可能遇到的性能问题及优化方案。
27.0万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

利用高阶组件封装复杂生命周期逻辑

  1. 创建高阶组件
    • 定义一个函数,该函数接收一个组件作为参数,并返回一个新的组件。
    • 在新组件中,利用React的生命周期方法(如componentDidMountcomponentDidUpdate)来处理复杂逻辑。
    • 例如:
import React from'react';

const withComplexLifecycle = (WrappedComponent) => {
    return class extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                data1: null,
                data2: null
            };
        }
        componentDidMount() {
            // 发起多个异步请求
            Promise.all([
                fetch('url1'),
                fetch('url2')
            ]).then(([res1, res2]) => res1.json().then(data1 => res2.json().then(data2 => ({data1, data2}))))
              .then(({data1, data2}) => {
                    this.setState({data1, data2});
                });
        }
        componentDidUpdate(prevProps) {
            // 处理不同类型的props变化
            if (prevProps.someProp!== this.props.someProp) {
                // 进行相应操作
            }
        }
        render() {
            const {data1, data2} = this.state;
            let content;
            if (data1 && data2) {
                // 根据不同条件渲染不同内容
                if (data1.someCondition && data2.someCondition) {
                    content = <div>满足条件的内容</div>;
                } else {
                    content = <div>其他内容</div>;
                }
            } else {
                content = <div>加载中...</div>;
            }
            return (
                <WrappedComponent {...this.props}>
                    {content}
                </WrappedComponent>
            );
        }
    };
};

export default withComplexLifecycle;
  1. 使用高阶组件
    • 在需要复用该逻辑的组件上应用高阶组件。
    • 例如:
import React from'react';
import withComplexLifecycle from './withComplexLifecycle';

const MyComponent = () => {
    return (
        <div>
            {/* 组件内容 */}
        </div>
    );
};

export default withComplexLifecycle(MyComponent);

可能遇到的性能问题及优化方案

  1. 性能问题
    • 不必要的渲染:高阶组件中的setState可能会导致包裹的组件不必要地重新渲染,即使props没有变化。
    • 异步请求重复:如果在componentDidUpdate中没有正确处理,可能会导致异步请求重复发起。
  2. 优化方案
    • 使用React.memo:对于包裹的组件,可以使用React.memo进行浅比较,防止不必要的渲染。例如:
import React from'react';
const MyComponent = React.memo(() => {
    return (
        <div>
            {/* 组件内容 */}
        </div>
    );
});
  • 优化异步请求逻辑:在componentDidUpdate中添加条件判断,只有在特定props变化且满足一定条件时才重新发起异步请求。例如:
componentDidUpdate(prevProps) {
    if (prevProps.someProp!== this.props.someProp && this.props.someProp === '特定值') {
        // 重新发起异步请求
    }
}
  • 数据缓存:对于异步请求的数据,可以进行缓存,避免重复请求相同的数据。可以使用WeakMap等数据结构来实现简单的缓存机制。例如:
const cache = new WeakMap();
const fetchData = async (url) => {
    if (cache.has(url)) {
        return cache.get(url);
    }
    const res = await fetch(url);
    const data = await res.json();
    cache.set(url, data);
    return data;
};
  • 节流与防抖:如果props变化频繁,可以使用节流或防抖技术来限制异步请求的频率,减少不必要的性能开销。例如,使用lodashdebounce函数:
import {debounce} from 'lodash';

class extends React.Component {
    constructor(props) {
        super(props);
        this.debouncedUpdate = debounce(this.handleUpdate, 300);
    }
    componentDidUpdate(prevProps) {
        if (prevProps.someProp!== this.props.someProp) {
            this.debouncedUpdate();
        }
    }
    handleUpdate() {
        // 处理更新逻辑,如发起异步请求
    }
    componentWillUnmount() {
        this.debouncedUpdate.cancel();
    }
}