@misaka17535/create-typed-event
v1.0.17
Published
Function-based and directive tiny typed event, with current value and optional react hook. Proven and well-tested in private projects. 全功能、函数式调用的微型事件库,可读取当前值且带有可选 react hook。在内部项目中久经考验。
Maintainers
Readme
create-typed-event
中文 | English
Typed . Autocomplete . One call unsubscribe . React is Optional
A simple eventManager, with built-in react support.
Best practices refined over five years. Proven and well-tested in private projects.
......And seriously, what's so bad about jumper wiring?
History on gist: https://gist.github.com/Misaka-0x447f/0c37018ae7bd944cbff54d27b6d4fd9f
Compares
| | typed | easy to use | perf | autocomplete | one call unsub | no React | latestValue | |--------------------|------------|---------|-------|------|--------|------------|----------| | create-typed-event | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | redux | *️⃣ 1 | ❌ | *️⃣ 5 | ✅ | ✅ | ✅ | ✅ | | mitt | *️⃣ 2 | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | | jotai | ✅ | *️⃣ 3 | ✅ | ✅ | ✅ | ❌ | *️⃣ 8 | | valtio | ✅ | *️⃣ 4 | *️⃣ 6 | ✅ | ✅ | ✅ | ✅ | | rxjs | ✅ | ❌ | *️⃣ 7 | ✅ | ✅ | ✅ | ✅ |
*1: Reducer required
*2: All key shares same type
*3: Two step create, atom & store
*4: Proxy based, which means just like vue 3, has it's trace limitation.
*5: Heavy slice
*6: v8 may not play well with proxy
*7: Really heavy even with rxjs subject
*8: Need to use default store
Detailed compares
- redux
- Toooooooooooo complex. To emit a state you have to create a new reducer, with a new store, a string store name...
- mitt / nodejs
EventEmitter- Requires you to write event name just like node.js
EventEmitter:emitter.on('xxx'..., which is not friendly to autocomplete. And why not put key in payload? - Does not return an unsub method.
- Does not support getting current value.
- Requires you to write event name just like node.js
- jotai
- To create a equivalent, you have to create an atom, then a store. And it requires user to create store every time user needs to subscribe.
- Does not support getting current value outside react context. See jotai issue
- valtio
- A good solution, but powered by Proxy, which is not really efficient and not working with complex object.
- rxjs
- Its Objective: requires you to create an Observable/Subject object, with the "new" statement we hate.
- Way much larger package size and more complex API.
- so many others
- Almost every library I know requires you to write event name on subscription, and cannot auto-complete.
- So I trust the solution I made can be unique and useful.
Examples
Traditional unsubscribe:
import { createTypedEvent } from '@misaka17535/create-typed-event'
type Payload = { ready: boolean }
const networkStateChange = createTypedEvent<Payload>()
const handler = (payload: Payload) => console.log(payload)
networkStateChange.sub(handler)
networkStateChange.dispatch({ready: true})
networkStateChange.unsub(handler)>>> { ready: true }
Simplified unsubscribe:
import { createTypedEvent } from '@misaka17535/create-typed-event'
const misakaStateChange = createTypedEvent<{ selfDestructionInProgress: boolean }>()
const unsub = misakaStateChange.sub((payload) => console.log(payload)) // returns unsub function without defining handler outside
misakaStateChange.dispatch({selfDestructionInProgress: true})
unsub()>>> { selfDestructionInProgress: true }
Create an "event bus":
import { createTypedEvent } from '@misaka17535/create-typed-event'
export const eventBus = {
alice: createTypedEvent(),
bob: createTypedEvent<{ isE2eEncryption: boolean }>()
}
eventBus.bob.dispatch({isE2eEncryption: true})Supports react hook:
import { createTypedEventMemorized } from '@misaka17535/create-typed-event/react'
const marketPriceUpdateEvent = createTypedEventMemorized<number>();
import { useTypedEventValue } from '@misaka17535/create-typed-event/react'
const [marketPrice, setMarketPrice, marketPriceRef] = useTypedEventValue(marketPriceUpdateEvent);API
import { createTypedEvent, type TypedEvent } from '@misaka17535/create-typed-event'
type TypedEvent<Payload>- The type that "createTypedEvent" returns.
createTypedEvent<Payload>(dispatchLastValueOnSubscribe?: boolean): TypedEvent<Payload>Create a new event unit.- Parameter
dispatchLastValueOnSubscribeoptional, default tofalse.
IfdispatchLastValueOnSubscribeis true, it will dispatch the last value to new subscribers.
- Returns an object with the following:
sub(callback: (payload: Payload) => void): () => void
Subscribe to event. Returns an unsub method that does not require original callback.unsub(callback: (payload: Payload) => void): voidUnsubscribe from event with the original callback.dispatch(payload: Payload): void
Dispatch an event with the given payload.once(callback: (payload: Payload) => void): () => void
Subscribe to event, but only once. Returns an unsub method that does not require original callback.get value(): Payload | undefined
A getter to get the current value of the event.
- Parameter
import { useTypedEvent, createTypedEventMemorized } from '@misaka17535/create-typed-event/react'
useTypedEvent(event: TypedEvent): HybridStateUse typed event as a React state.- Returns a tuple of:
value: Payload | undefined
The current value of the event.setValue: (payload: Payload) => void
A function to set the value of the event.ref: React.MutableRefObject<Payload | undefined>
Arefthat holds the current value of the event, useful for accessing the latest value in effects or callbacks.
- Returns a tuple of:
createTypedEventMemorized<Payload>(dispatchLastValueOnSubscribe?: boolean)CreateTypedEventwithin react component. Parameters and returns are the same ascreateTypedEvent.
