Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

evently-react

tirth-200171MIT1.0.0TypeScript support: included

A Hook-Based Framework for Event-Driven React Apps

react-event, useEvent, event-management, event, event-bus, pub-sub, hooks, middleware, state-management, react-hooks, event-driven-architecture, typescript, in-memory-cache, scalable, react

readme

evently-react

A Hook-Based Framework for Event-Driven React Apps


Banner

npm Downloads typescript

📜 Table of Contents

  1. 🎉 Overview
  2. ⚡ Features
  3. 🚀 Getting Started
  4. 🌟 Use Cases and Kickstarters
  5. 🔧 Usage
  6. 🕹️ Advanced Features
  7. 🔄 Comparison with Redux and Prop Drilling
  8. 💡 Tips
  9. 📝 FAQs
  10. 🛠️ Support and Suggestion

🎉 Overview

evently-react simplifies event management for React developers. 🚀

Whether you're building a small app or a large-scale application, this package offers a clean and simplified design to manage robust and scalable event-driven architectures.

With its hooks-based API, evently-react enables seamless event handling while keeping your codebase clean and maintainable.

Say goodbye to prop drilling & global state chaos and hello to elegant, event-driven designs! 🎯


⚡ Features

  • 💡 Hooks-based API: Simplifies event management with useSubscribe, useEvent, and useSubscribeState.
  • 🧩 In-memory Caching: Supports late subscribers without missing events.
  • 🔗 Middleware Support: Modify or intercept event payloads seamlessly.
  • 📂 Typed Events: Built-in TypeScript support ensures type safety.
  • ⚙️ Non-React Compatibility: Use exported EventBus class for other environments.

🚀 Getting Started

1️⃣ Installation

Install the package using npm or yarn:

npm install evently-react
# OR
yarn add evently-react

2️⃣ Quickstart Example

Below is a quick example to get started with evently-react.

import React from 'react'
import { EventProvider, useEvent, useSubscribe } from 'evently-react'

// Define a publisher component
const Publisher: React.FC = () => {
  const { emitEvent } = useEvent()

  const handleClick = () => {
    emitEvent('greet', { message: 'Hello from Publisher!' }) // Emit an event
  }

  return <button onClick={handleClick}>Send Greeting</button>
}

// Define a subscriber component
const Subscriber: React.FC = () => {
  useSubscribe('greet', (eventName, payload) => {
    console.log(payload.message) // Log the event payload
  })

  return <p>Listening for greetings...</p>
}

// Wrap your application with EventProvider
const App: React.FC = () => (
  <EventProvider>
    <Publisher />
    <Subscriber />
  </EventProvider>
)

export default App

🌟 Use Cases and Kickstarters

evently-react is designed to simplify communication in complex React applications. Here are some inspiring real-world use cases to help you explore its potential:

1️⃣ Cross-Component Communication

Emit an event in one component and listen to it in another—no need for prop drilling or context juggling.

Example:

  • A button in a header component emits an event to toggle a sidebar menu managed by a sibling component.
// In Header component
emitEvent('toggleSidebar', { isVisible: true })

// In Sidebar component
useSubscribe('toggleSidebar', (eventName, payload) => setSidebarVisible(payload.isVisible))

2️⃣ Global Notifications

Create a centralized system for displaying notifications (like toast messages) triggered from anywhere in your app.

Example:

  • A failed API call emits an event to show an error toast notification.
emitEvent('showToast', { type: 'error', message: 'Failed to fetch data!' })

3️⃣ Dynamic Data Updates

Trigger UI updates in real-time when backend events or user actions occur.

Example:

  • A WebSocket listener emits data updates that a dashboard component subscribes to for live charts or metrics.
// WebSocket listener emits new data
emitEvent('updateMetrics', newMetrics)

// Dashboard listens to updates
useSubscribe('updateMetrics', (eventName, metrics) => updateChart(metrics))

4️⃣ Hybrid State/Event Management

Combine event-driven architecture with existing state management tools (e.g., Redux or Context API) for specific, modular use cases.

Example:

  • Use events for decoupled interactions like resetting forms or syncing components without modifying the global state.
// Emit form reset event
emitEvent('resetForm')

// Form component subscribes to reset action
useSubscribe('resetForm', (eventName, payload) => setFormData(initialValues))

By adopting evently-react, you can create scalable, decoupled, and maintainable solutions for modern web applications. 🎯


🔧 Usage

Emitting Events

Use the useEvent hook to emit events:

import React from 'react'
import { useEvent } from 'evently-react'

const EmitExample: React.FC = () => {
  const { emitEvent } = useEvent()

  const handleClick = () => {
    emitEvent('exampleEvent', { message: 'Hello, Evently!' }) // Emit an event with a payload
  }

  return <button onClick={handleClick}>Emit Event</button>
}

export default EmitExample

Subscribing to Events

Use the useSubscribe hook to listen to events:

import React from 'react'
import { useSubscribe } from 'evently-react'

const SubscribeExample: React.FC = () => {
  useSubscribe('exampleEvent', (eventName, payload) => {
    console.log('Received payload:', payload) // Logs: { message: 'Hello, Evently!' }
  })

  return <p>Listening for events...</p>
}

export default SubscribeExample

Subscribing to Multiple Events

Use the enhanced useSubscribe hook to listen to multiple events:

import React from 'react'
import { useSubscribe } from 'evently-react'

const MultiSubscribeExample: React.FC = () => {
  useSubscribe(['eventOne', 'eventTwo'], (eventName, payload) => {
    console.log(`Received payload for ${eventName}:`, payload)
  })

  return <p>Listening for multiple events...</p>
}

export default MultiSubscribeExample

Using State from Events

Leverage the useSubscribeState hook to access the latest event payload as state:

import React from 'react'
import { useSubscribeState } from 'evently-react'

const StateExample: React.FC = () => {
  const latestEventPayload = useSubscribeState('exampleEvent')

  return <p>Latest Payload: {latestEventPayload?.message}</p>
}

export default StateExample

🕹️ Advanced Features

Middlewares 🔗

Middleware allows you to intercept or transform events before they are processed.

Global Middleware: .use()

import { useEvent } from 'evently-react'

const App = () => {
  const { eventBus } = useEvent()

  eventBus.use((event, payload) => {
    console.log(`Global Middleware: ${event}`)
    return { ...payload, eventSeen: true }
  })

  return <div>Your App</div>
}

Event-Specific Middleware: .useForEvent()

eventBus.useForEvent('myEvent', (event, payload) => {
  console.log(`Event middleware for ${event}`)
  return { ...payload, transformed: true }
})

In-Memory Caching 📦

Late subscribers can still receive the latest events:

useSubscribe('exampleEvent', (eventName, payload) => {
  console.log('Late subscriber received:', payload) // Works even if the event was emitted earlier
})

Priority-Based Subscription 🚦

Control the execution order of event handlers by assigning priorities. Higher priority callbacks execute first (default is 0).

// Low priority handler.
useSubscribe('important-event', (eventName, payload) => console.log('Low priority'), 1)

// High priority handler.
useSubscribe('important-event', (eventName, payload) => console.log('High priority'), 3)

Handlers are executed in descending order of priority, making it easy to manage complex event flows.


Accessing EventBus Instance 🚌

The eventBus instance, accessible via the useEvent hook, allows integration of evently-react into non-Component environments such as utility functions or external libraries. This enables advanced use cases like chaining events, transforming payloads, or other customized workflows.

Example: Using EventBus in Utility Functions

The following example demonstrates how to pass the eventBus instance to a utility function for chaining events:

// Component file
import { useEvent } from 'evently-react'
import { handleEventChain } from './utils'

const Component = () => {
  const { eventBus } = useEvent()

  // Pass the eventBus instance to utility functions
  handleEventChain('logoutUser', eventBus)

  return <div>Event Handling Component</div>
}

// utils.ts
import { EventBus } from 'evently-react'

export function handleEventChain(eventName: string, eventBus: EventBus) {
  eventBus.subscribe(eventName, payload => {
    if (payload.action === 'logout') {
      console.log('Logging out user...')

      // Emitting new event based on received payload
      eventBus.emit('resetPreferences', { message: 'Resetting preferences...' })
    }
  })
}

Use Cases:

  • Chaining Events: Trigger subsequent events based on specific payload conditions.
  • Transforming Payloads: Modify or enrich event data before emission using middlewares.
  • Non-Component Interactions: Handle events in service layers, utility files, or middleware systems.

Tip: If the use case is completely non-React, consider using the EventBus class directly. Instead of using hooks, you can create an instance of EventBus and leverage its methods for event management.

This feature extends the power of evently-react beyond React components, enabling seamless integration in diverse workflows. 🚀


🔄 Comparison with Redux and Prop Drilling

Feature Redux Equivalent evently-react Alternative
Dispatch actions dispatch emitEvent
Select state useSelector useSubscribeState
Middleware/Event Processing thunks/sagas Global & Event-specific Middleware
Centralized store & reducer boilerplate Required Not Required
Prop drilling Problematic Eliminated

Inject evently-react seamlessly into existing projects and reduce boilerplate while maintaining scalability.

Note: evently-react is not intended to replace Redux/Context API or prop drilling entirely. Instead, it provides a complementary event-driven approach to simplify code and improve scalability. By leveraging this pattern, you can reduce boilerplate and decouple components without sacrificing existing architecture.


💡 Tips

  • 🎯 Use meaningful event names to keep your event flow intuitive.
  • 💾 Middleware can be a powerful way to enforce validation or transformations across events.
  • ⚙️ Use in-memory caching to ensure real-time updates for dynamic UIs.
  • 🧩 Combine evently-react with React context or Redux for hybrid state/event management solutions.
  • 📦 Explore lazy-loaded modules to reduce initial app load while still utilizing events.

📝 FAQs

1️⃣ What is a real-world use case for evently-react?

  • Cross-Component Communication: Emit an event in one component and listen in another without prop drilling.
  • Global Notifications: Show toast notifications across your app.
  • Dynamic Data Updates: Trigger real-time UI updates based on backend events.

2️⃣ How do I define types for events in my project?

  • Create an evently.d.ts file in your project and extend the Events type:
import 'evently-react'

declare module 'evently-react' {
  export interface Events {
    showToast: { message: string; duration: number }
    setTheme: { theme: 'light' | 'dark' }
  }
}

3️⃣ Can I use evently-react in non-React environments?

  • Yes! You can use the exported EventBus class instance to integrate event-based communication in non-React environments. (Example: Vanilla JS, Angular and other frameworks) All methods like emit, subscribe, and middleware support are fully available.

4️⃣ How to subscribe multiple events in one component?

  • Simply call useSubscribe and give array of event names as parameter. It will listen to all the events provided in the array.

5️⃣ Is there a plan to support other frameworks?

  • Yes, there are plans to release individual packages for other frameworks in the future.

🛠️ Support and Suggestion

Having issues or have a suggestion?