UNPKG

evently-react

Version:

A Hook-Based Framework for Event-Driven React Apps

450 lines (300 loc) β€’ 14.3 kB
<div align="center"> <h1> evently-react </h1> <h3> A Hook-Based Framework for Event-Driven React Apps </h3> <br /> ![Banner](https://i.ibb.co/7KPsLmW/title-banner.png) </div> ![npm](https://img.shields.io/npm/v/evently-react?style=flat-square) ![Downloads](https://img.shields.io/npm/dt/evently-react?style=flat-square) ![typescript](https://img.shields.io/badge/TypeScript-Supported-blue?style=flat-square) ## πŸ“œ Table of Contents 1. [πŸŽ‰ Overview](#-overview) 2. [⚑ Features](#-features) 3. [πŸš€ Getting Started](#-getting-started) - [Installation](#1️⃣-installation) - [Quickstart Example](#2️⃣-quickstart-example) 4. [🌟 Use Cases and Kickstarters](#-use-cases-and-kickstarters) - [Cross-Component Communication](#1️⃣-cross-component-communication) - [Global Notifications](#2️⃣-global-notifications) - [Dynamic Data Updates](#3️⃣-dynamic-data-updates) - [Hybrid State/Event Management](#4️⃣-hybrid-stateevent-management) 5. [πŸ”§ Usage](#-usage) - [Emitting Events](#emitting-events) - [Subscribing to Events](#subscribing-to-events) - [Subscribing to Multiple Events](#subscribing-to-multiple-events) - [Using State from Events](#using-state-from-events) 6. [πŸ•ΉοΈ Advanced Features](#-advanced-features) - [Middlewares](#middlewares-) - [In-Memory Caching](#in-memory-caching-) - [Priority-Based Subscription](#priority-based-subscription-) - [Accessing EventBus Instance](#accessing-eventbus-instance-) 7. [πŸ”„ Comparison with Redux and Prop Drilling](#-comparison-with-redux-and-prop-drilling) 8. [πŸ’‘ Tips](#-tips) 9. [πŸ“ FAQs](#-faqs) 10. [πŸ› οΈ Support and Suggestion](#-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: ```bash npm install evently-react # OR yarn add evently-react ``` ### 2️⃣ Quickstart Example Below is a quick example to get started with `evently-react`. ```tsx 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. ```tsx // 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. ```tsx 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. ```tsx // 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. ```tsx // 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: ```tsx 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: ```tsx 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: ```tsx 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: ```tsx 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()` ```tsx 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()` ```tsx 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: ```tsx 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`). ```tsx // 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: ```tsx // 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: ```tsx 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? - 🐞 [Report a Bug](https://github.com/tirth-2001/evently-react/issues/new?assignees=&labels=bug&projects=&template=bug_report.md&title=%5BBug%5D+) - πŸ’‘ [Request a Feature](https://github.com/tirth-2001/evently-react/issues/new?assignees=&labels=enhancement&projects=&template=feature_request.md&title=%5BFeature%5D+) - πŸ“š [Join the Discussion](https://github.com/tirth-2001/evently-react/discussions)