面试题:如何将事件传递给 React 子组件?

在 React 中,由于事件处理逻辑通常位于父组件,而事件触发于子组件(如按钮点击),因此需要将事件处理函数从父组件作为 props 传递给子组件。这是 React 数据和逻辑自上而下流动的典型体现。

以下是几种常见的传递方式:

1. 通过 Props 传递回调函数(最常用)

这是最基础、最推荐的方式。父组件定义事件处理函数,并通过 props 传递给子组件。

// 子组件
function Button({ onClick, children }) {
  return (
    <button onClick={onClick}>
      {children}
    </button>
  );
}

// 父组件
function Parent() {
  const handleClick = () => {
    console.log('按钮被点击了!');
  };

  return (
    <div>
      <Button onClick={handleClick}>点击我</Button>
    </div>
  );
}

2. 传递参数给子组件的事件处理器

有时需要在子组件中触发事件时传递额外数据。可以在父组件中使用箭头函数包裹,或在子组件中调用时传参。

方式一:父组件使用箭头函数传参

function Parent() {
  const handleItemClick = (id) => {
    console.log(`项目 ${id} 被点击`);
  };

  return (
    <ul>
      <li><Button onClick={() => handleItemClick(1)}>项目 1</Button></li>
      <li><Button onClick={() => handleItemClick(2)}>项目 2</Button></li>
    </ul>
  );
}

方式二:子组件在触发时传参

// 子组件
function Item({ id, onItemClick }) {
  return (
    <div onClick={() => onItemClick(id)}>
      项目 {id}
    </div>
  );
}

// 父组件
function Parent() {
  const handleItemClick = (id) => {
    console.log(`项目 ${id} 被点击`);
  };

  return (
    <div>
      <Item id={1} onItemClick={handleItemClick} />
      <Item id={2} onItemClick={handleItemClick} />
    </div>
  );
}

3. 使用 useCallback 优化(避免不必要的重渲染)

当子组件是 React.memo 优化过的纯组件时,频繁传递新的函数引用会导致子组件不必要的重渲染。可以使用 useCallback 缓存事件处理函数。

import React, { useCallback } from 'react';

function Parent() {
  const handleSave = useCallback(() => {
    console.log('保存数据');
  }, []); // 空依赖数组,函数不会改变

  return (
    <div>
      <ExpensiveChild onSave={handleSave} />
    </div>
  );
}

4. 通过 Context 传递(适用于深层嵌套)

当组件层级较深,逐层传递 props 显得繁琐时(“props drilling”),可以使用 React Context

// 创建 Context
const EventContext = React.createContext();

// 父组件(提供者)
function Parent() {
  const handleClick = () => {
    console.log('深层组件触发点击');
  };

  return (
    <EventContext.Provider value={{ handleClick }}>
      <Child />
    </EventContext.Provider>
  );
}

// 深层子组件(消费者)
function DeepChild() {
  const { handleClick } = React.useContext(EventContext);

  return <button onClick={handleClick}>深层按钮</button>;
}

5. 使用自定义 Hook 封装逻辑

将事件处理逻辑封装到自定义 Hook 中,提高复用性。

// 自定义 Hook
function useClickHandler() {
  const handleClick = () => {
    console.log('通用点击处理');
  };
  return { handleClick };
}

// 组件中使用
function MyComponent() {
  const { handleClick } = useClickHandler();

  return <Button onClick={handleClick}>点击</Button>;
}

总结

  • 首选方式:通过 props 传递回调函数。
  • 性能优化:配合 useCallbackReact.memo 避免不必要渲染。
  • 深层传递:使用 Context 避免 props drilling。
  • 逻辑复用:使用自定义 Hook 封装事件逻辑。

核心思想是:React 鼓励将状态和逻辑保留在上层组件,通过 props 将行为(函数)向下传递,保持组件的解耦和可预测性。

THE END
喜欢就支持一下吧
点赞10 分享