npm i @bit-about/event
v1 -> v2
Events dispatch approach has been changed. There are no longer functions executed using their names in string.
βοΈ old one:
const dispatch = useEvent() dispatch('onBobPress', 'hello')β new one:
const { onBobPress } = useEvent() onBobPress('hello')
- 100% Idiomatic React
- 100% Typescript with event types deduction
- Listen or dispatch events from a hook...
- ...or utilise static access
- No centralized event provider
- Tiny - only 0.6kB
- Just works β’
β‘οΈ Check demo
1οΈβ£ Define your events by defining their payload middlewares
import { events } from '@bit-about/event'
const [EventProvider, useEvents] = events({
buttonClicked: (payload: string) => payload,
userLogged: () => {},
modalClosed: () => {},
})
2οΈβ£ Wrap your components in EventProvider
const App = () => (
<EventProvider>
...
</EventProvider>
)
π£οΈ Dispatch your events in one place...
const Button = () => {
const { buttonClicked } = useEvents()
return (
<button onClick={() => buttonClicked('Hello')}>
Call event
</button>
)
}
π ...and listen for them in another
const Component = () => {
const [message, setMessage] = React.useState('')
useEvents({
buttonClicked: (payload: string) => setMessage(payload)
})
return <p>{message}</p> // "Hello"
}
The third result element of events()
is object providing access in static manner (without hook).
const [AppEventProvider, useAppEvents, { subscribe, dispatcher }] = events(...)
and then
// π£οΈ Dispatch event
dispatcher.buttonClicked('Hello Allice!')
// π Subscribe and listen on new events
const subscriber = subscribe({
buttonClicked: (payload: string) => console.log(payload)
})
// remember to unsubscribe!
subscriber.unsubscribe()
Neither listeners nor events dispatch your components render.
A component will only be rerendered if it's state is explicitly changed (in e.g. React.useState
).
const Component = () => {
const [message, setMessage] = React.useState('')
useEvents({
aliceClicked: () => console.log('I DO NOT rerender this component!'),
bobClicked: () => setMessage('I DO rerender this component!')
})
return <p>{message}</p>
}
Events in events()
are payload middlewares. They can transform payload into another.
const [EventProvider, useEvents] = events({
buttonClicked: (payload) => `Hello ${message}!`, // Transforms string payload to another
avatarClicked: () => `Bob!`, // Provides default payload
})
const { buttonClicked, avatarClicked } = useEvents({
buttonClicked: (payload) => console.log(payload), // prints "Hello Alice!",
avatarClicked: (payload) => console.log(payload), // prints "Bob!"
})
buttonClicked('Alice')
avatarClicked()
NOTE:
The library is full type-safe, so Typescript will inform you when you use wrong payload anywhere.
BitAboutEvent π BitAboutState
Are you tired of sending logic to a related components?
Move your bussiness logic to hook-based state using @bit-about/state
+ @bit-about/event
.
Now you've got completely type-safe side-effects. Isn't that cool?
import { state } from '@bit-about/state'
import { useEvents } from './auth-events' // Hook generated from events()
import User from '../models/user'
const [UserProvider, useUser] = state(
() => {
const [user, setUser] = React.useState<User | null>(null)
useEvents({
userLogged: (user: User) => setUser(user),
userLoggout: () => setUser(null)
})
return user
}
)
- Constate - approach main inspiration
- use-context-selector & FluentUI - fancy rerender avoiding tricks and code main inspiration
MIT Β© Maciej Olejnik π΅π±
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