MST

星途 面试题库

面试题:如何在React函数式组件中避免因事件处理导致的内存泄漏

假设你正在开发一个React函数式组件,其中绑定了多个事件处理函数。请详细说明你会采取哪些措施来确保在组件卸载时,这些事件处理不会造成内存泄漏,结合useEffect、useCallback等Hook进行阐述。
29.0万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试
  1. 使用useCallback缓存事件处理函数
    • 当事件处理函数依赖于组件的props或state时,使用useCallback可以避免每次渲染都创建新的函数实例。例如:
    import React, { useCallback, useState } from'react';
    
    const MyComponent = () => {
      const [count, setCount] = useState(0);
    
      const handleClick = useCallback(() => {
        setCount(count + 1);
      }, [count]);
    
      return <button onClick={handleClick}>Click me</button>;
    };
    
    export default MyComponent;
    
    • 这样,只有当count发生变化时,handleClick函数才会重新创建,减少不必要的渲染和函数创建开销。
  2. 使用useEffect进行事件绑定和解绑
    • useEffect中进行事件绑定操作,并且在返回的清理函数中解绑事件。例如,假设要绑定一个全局的resize事件:
    import React, { useEffect, useCallback } from'react';
    
    const MyComponent = () => {
      const handleResize = useCallback(() => {
        // 处理resize事件的逻辑
        console.log('Window resized');
      }, []);
    
      useEffect(() => {
        window.addEventListener('resize', handleResize);
        return () => {
          window.removeEventListener('resize', handleResize);
        };
      }, [handleResize]);
    
      return <div>My Component</div>;
    };
    
    export default MyComponent;
    
    • 在这个例子中,useEffect依赖数组中包含handleResize,确保只有当handleResize函数发生变化时(由于useCallback的存在,只有依赖项变化时handleResize才会变化),才会重新绑定和解绑事件。
    • 如果事件处理函数依赖于组件的state或props,那么这些依赖项也应该包含在useEffect的依赖数组中。例如:
    import React, { useEffect, useCallback, useState } from'react';
    
    const MyComponent = () => {
      const [count, setCount] = useState(0);
    
      const handleResize = useCallback(() => {
        // 处理resize事件的逻辑,这里可以使用count
        console.log(`Window resized, count: ${count}`);
      }, [count]);
    
      useEffect(() => {
        window.addEventListener('resize', handleResize);
        return () => {
          window.removeEventListener('resize', handleResize);
        };
      }, [handleResize]);
    
      return (
        <div>
          <p>Count: {count}</p>
          <button onClick={() => setCount(count + 1)}>Increment</button>
        </div>
      );
    };
    
    export default MyComponent;
    
    • 这样,当count变化时,handleResize函数会重新创建,useEffect也会重新执行,正确地解绑旧的事件监听并绑定新的事件监听,避免内存泄漏。