MST

星途 面试题库

面试题:React自定义事件在复杂组件层次结构中的应用与优化

假设有一个多层嵌套的React组件结构,最内层组件需要触发一个自定义事件,这个事件要传递到最外层组件进行处理,同时在传递过程中可能需要对事件数据进行一些处理。请设计一种合理的架构并实现它,说明如何保证性能优化,避免不必要的渲染。
29.7万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

1. 设计架构

  • 使用React的Context:Context 提供了一种在组件之间共享数据的方式,而无需在组件树中通过 props 层层传递。
  • 自定义事件处理:在最内层组件触发自定义事件,通过 Context 将事件传递到最外层组件。
  • 中间层处理:中间层组件可以通过 Context 订阅事件,对事件数据进行处理后再传递给下一层。

2. 实现代码

import React, { createContext, useState, useEffect } from'react';

// 创建Context
const CustomEventContext = createContext();

// 最内层组件
const InnerComponent = () => {
    const { onCustomEvent } = React.useContext(CustomEventContext);

    const handleClick = () => {
        const eventData = { message: 'This is a custom event from inner component' };
        onCustomEvent(eventData);
    };

    return (
        <button onClick={handleClick}>Trigger Custom Event</button>
    );
};

// 中间层组件(假设需要处理事件数据)
const MiddleComponent = () => {
    const { onCustomEvent } = React.useContext(CustomEventContext);

    useEffect(() => {
        const handleInnerEvent = (data) => {
            // 处理事件数据,例如添加时间戳
            const newData = { ...data, timestamp: new Date().getTime() };
            onCustomEvent(newData);
        };

        // 订阅事件
        if (onCustomEvent) {
            onCustomEvent.subscribe(handleInnerEvent);
        }

        return () => {
            // 取消订阅
            if (onCustomEvent) {
                onCustomEvent.unsubscribe(handleInnerEvent);
            }
        };
    }, [onCustomEvent]);

    return (
        <div>
            <InnerComponent />
        </div>
    );
};

// 最外层组件
const OuterComponent = () => {
    const [eventData, setEventData] = useState(null);

    const customEventEmitter = {
        handlers: [],
        subscribe: (handler) => {
            this.handlers.push(handler);
        },
        unsubscribe: (handler) => {
            this.handlers = this.handlers.filter(h => h!== handler);
        },
        emit: (data) => {
            this.handlers.forEach(handler => handler(data));
        }
    };

    const handleCustomEvent = (data) => {
        setEventData(data);
    };

    return (
        <CustomEventContext.Provider value={{ onCustomEvent: customEventEmitter }}>
            <div>
                <h1>Outer Component</h1>
                {eventData && (
                    <div>
                        <p>Received Event Data: {JSON.stringify(eventData)}</p>
                    </div>
                )}
                <MiddleComponent />
            </div>
        </CustomEventContext.Provider>
    );
};

export default OuterComponent;

3. 性能优化

  • 使用 React.memo:对于中间层组件和最内层组件,如果它们的 props 没有变化,可以使用 React.memo 包裹,避免不必要的渲染。例如:
const InnerComponent = React.memo(() => {
    // 组件内容
});

const MiddleComponent = React.memo(() => {
    // 组件内容
});
  • 减少 Context 更新频率:在最外层组件中,尽量将 onCustomEvent 相关逻辑提取到一个单独的对象中,并保持该对象引用稳定,避免因为对象重新创建导致 Context 更新,进而引发不必要的渲染。如上述代码中 customEventEmitter 的设计。
  • 事件订阅与取消:在中间层组件中,使用 useEffect 进行事件订阅和取消,确保在组件卸载时取消订阅,避免内存泄漏,同时减少不必要的事件处理重复执行。