GitHub - bit-about/event: 💫 Tiny and powerful hook-based event system for React
source link: https://github.com/bit-about/event
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Install
npm i @bit-about/event
Features
- 100% Idiomatic React
- 100% Typescript with event types deduction
- Efficient and hook-based
- ...with static listener and dispatcher
- No centralized event provider
- Tiny - only 1.6kB
- Just works ™
Usage
Define your events set and their payloads
import { events } from '@bit-about/event' const [EventProvider, useEvent] = events({ buttonClicked: (payload: string) => payload, userLogged: () => {}, modalClosed: () => {}, })
Wrap the tree with the EventProvider
const App = () => ( <EventProvider> ... </EventProvider> )
Dispatch your events
const Button = () => { const dispatch = useEvent() const onClick = () => dispatch('buttonClicked', 'Hello') return <button onClick={onClick}>Call event</button> }
Listen on your events
const Component = () => { const [message, setMessage] = React.useState('') useEvent({ buttonClicked: (payload: string) => setMessage(payload) }) return <p>{message}</p> }
Static access
The third element of the events()
result tuple is object which provides access in static manner (without hook).
const [AppEventProvider, useAppEvent, appEvent] = events(...)
and then
// 🗣️ Dispatch event appEvent.dispatch('buttonClicked', 'Hello Allice!') // 👂 Subscribe and listen on new events const subscriber = appEvent.subscribe({ buttonClicked: (payload: string) => console.log(payload) }) // remember to unsubscribe! subscriber.unsubscribe()
Rerendering
Neither listeners nor event dispatching rerender the component.
The component will only be rerendered if its state is explicitly changed (in e.g. React.useState
).
const Component = () => { const [message, setMessage] = React.useState('') useEvent({ aliceClicked: () => console.log('I DO NOT rerender this component!'), bobClicked: () => setMessage('I DO rerender this component!') }) return <p>{message}</p> }
Event Middlewares
Events in events()
are actually payload middlewares.
const [EventProvider, useEvent] = events({ buttonClicked: (payload: string) => `Hello ${message}!`, // Transforms string payload to another avatarClicked: () => `Bob!`, // Provides default payload }) const dispatch = useEvent({ buttonClicked: (payload: string) => console.log(payload), // "Hello Alice!", avatarClicked: (payload: string) => console.log(payload), // "Bob!" }) dispatch('buttonClicked', 'Alice') dispatch('avatarClicked')
NOTE:
The library is completely type safe so Typescript will inform you when you use wrong payload anywhere
BitAboutEvent BitAboutState
Are you tired of sending logic to the related components?
Move your bussiness logic to the hook-based state using @bit-about/state
+ @bit-about/event
.
Now you've got completely type-safe side-effects, isn't cool?
import { state } from '@bit-about/state' import { useEvent } from './auth-events' // Hook generated from events() import User from '../models/user' const [UserProvider, useUser] = state( () => { const [user, setUser] = React.useState<User | null>(null) useEvent({ userLogged: (user: User) => setUser(user), userLoggout: () => setUser(null) }) return user } )
Partners
Credits
- Constate - approach main inspiration
- use-context-selector & FluentUI - fancy rerender avoiding tricks and code main inspiration
License
Support me
If you use my library and you like it...
it would be nice if you put the name BitAboutEvent
in the work experience section of your resume.
Thanks 🙇🏻!
Slava Ukraini
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK