为了账号安全,请及时绑定邮箱和手机立即绑定

React中使用自定义事件轻松管理应用状态:简单而强大的方法

在构建 React 应用程序时,管理组件之间的状态可能会变得颇具挑战。虽然这些解决方案很流行,比如 Context API、Redux 或 Zustand,但我们还可以利用一个更简单的内置浏览器功能:自定义事件功能。

什么是自定义事件?

自定义事件是浏览器内置事件API的一部分,允许你在应用程序中创建和分发自定义事件。这种方式使得组件之间的通信更加轻量级且解耦。这无需你通过属性钻取(prop drilling)或使用复杂的状态管理库来实现。

为什么要使用自定义事件?

  1. 原生浏览器 API - 无需任何额外依赖。
  2. 解耦通信 - 组件可以独立通信。
  3. 简单实现 - 易于搭建和维护。
  4. 性能 - 比全局状态管理更轻量。
  5. 类型安全 - 可以完全用 TypeScript 定义类型。
实现例子

我们来看一个通过自定义事件实现模态窗口的实际案例。

1. 定义您的自定义事件类型
首先,定义您的自定义事件接口:

    export interface 自定义事件接口 {
      模态框事件: {
        action: '开启' | '关闭'
      }
    }

切换到全屏 退出全屏

2. 创建一个触发器函数:
创建一个辅助函数来分发自定义触发事件:

    // 触发自定义事件的函数
    export const triggerCustomEvent = <EventName extends keyof CustomEvents>(
      eventName: EventName,
      data: CustomEvents[EventName]
    ) => {
      // 创建一个新的自定义事件对象
      const event = new CustomEvent(eventName, { detail: data })
      // 在文档上分发事件
      document.dispatchEvent(event)
    }

全屏查看,退出全屏

3. 创建一个自定义钩子:
创建一个钩子用于监听自定义事件:

export function useEventListener<T extends keyof CustomEvents>(
  eventName: T,
  handler: (detail: CustomEvents[T]) => void
) {
  useEffect(() => {
    const eventHandler = (event: CustomEvent<CustomEvents[T]>) => {
      handler(event.detail)
    }

    document.addEventListener(eventName, eventHandler as EventListener)
    return () => {
      document.removeEventListener(eventName, eventHandler as EventListener)
    }
  }, [eventName, handler])
}

这是一个用于监听特定自定义事件的 Hook。它接收一个事件名称和一个处理函数,当指定的事件触发时,处理函数会被调用。

全屏 退出全屏

使用示例

下面是如何使用自定义事件来创建模态窗口:

触发模态:

    const handleOpenModal = () => {
      triggerCustomEvent('modal-event', { action: '打开模态框' })
    }

请点击点击全屏 请点击退出全屏。

模态框:

    // 导出一个名为 FeedbackModal 的 React 组件
    export const FeedbackModal: React.FC = () => {
      // 定义一个 isOpen 状态,初始值为 false
      const [isOpen, setIsOpen] = useState(false)

      // 监听 'modal-event' 事件,并根据事件中的 action 属性做出响应
      useEventListener('modal-event', ({ action }) => {
        // 根据 action 的值决定是否打开或关闭模态框
        switch (action) {
          case 'open':
            // 将 isOpen 状态设置为 true,以显示模态框
            setIsOpen(true)
            break
          case 'close':
            // 将 isOpen 状态设置为 false,以关闭模态框
            setIsOpen(false)
            break
        }
      })

切换到全屏 | 退出全屏

真实的好处

让我们来看一看一个实际场景,其中自定义事件在这里特别有用。在我们的示例应用中,我们有三个独立的组件(头部、内容和底部),这些组件都需要触发同一个模态框:

    默认导出一个名为Home的函数 {
      return (
        <div>
          <头部 />
          <内容 />
          <底部 />
          <反馈模态框 />
        </div>
      )
    }

全屏,退出全屏

不是,比如说:

  • 将状态提升到共同的父组件
  • 使用 Context API
  • 实现状态管理库
  • 属性穿透

我们只是简单地说:

  1. 定义我们自己的事件
  2. 从任何地方触发
  3. 在需要的地方监听

最佳做法

  • 确保类型安全:总是定义自己的事件接口
  • 命名事件:使用清晰且描述性强的名称
  • 清理:始终在 useEffect 清理中删除事件监听器
  • 保持事件负载简单明了

什么时候该使用自定义事件

自定义事件特别有用的情况包括:例如……

  • 组件需要在应用程序的不同部分之间通信
  • 您希望避免属性传递
  • 您需要一个轻量级的替代方案来处理全局状态
  • 组件需要对无关动作作出反应

何时不要使用自定义事件

当你需要考虑其他选项时:

  • 你需要保存状态
  • 你需要在多个标签页间同步状态
  • 你需要处理复杂的状态
  • 你需要追踪状态历史
最后

自定义事件(Custom Events)提供了一种简单且强大的方法来处理React应用中的组件通信。虽然它们可能在某些情况下无法替代复杂应用中的状态管理库,但为许多常见的场景提供了一个轻量级的解决方案。

这种方法的魅力在于其简洁和利用浏览器的原生功能。这提醒我们,有时候最好的解决方法就是利用平台本身的特性。

这一实现展示了我们如何利用浏览器 API 来创建清晰、简洁且无需额外依赖的代码。完整的示例代码可以在提供的仓库里找到,展示了自定义事件如何优雅地解决跨组件间通信的问题。

代码库: https://github.com/AdrianKnapp/custom-events (点击这里访问)
试试看: https://custom-events-iota.vercel.app/ —— (点击这里访问)

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消