npm i @bit-about/eventv1 -> 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

