0.0.7 • Published 4 years ago

@twopm/use-stream v0.0.7

Weekly downloads
1
License
MIT
Repository
github
Last release
4 years ago

This an exploration of an idea I've had for a while. While we've found that the built-in React hooks (useState, useReducer) are more than complete enough to replace a state management solution like redux, there is more to the picture.

redux is used as an event bus as often as it is used for state management. Libraries like redux-observable and redux-sagas are examples of this pattern in the wild. For me, this is valuable functionality and is missing in our out-of-the-box React setup.

So this is my attempt to bring it back! This is a set of hooks that can create an event bus (via observables) that is stored in context and can be subscribed to and emitted to from throughout the React application tree. Importantly, this is a separate stream to the actions that update our state which allows for better separation of concerns.

Installation

yarn add @twopm/use-stream

Setup

First, define the types of the events that will be sent along the bus.

export type MouseClicked = { type: 'mouseClicked' }
export type SpacePressed = { type: 'spacePressed' }
export type MouseMoved = { type: 'mouseMoved'; location: [number, number] }

export type Events = MouseClicked | SpacePressed | MouseMoved

Second, create the bus itself.

import { makeEventStream, makeEventStreamContext } from '@twopm/use-stream'

export const stream = makeEventStream<Events>('main')
export const EventStreamContext = makeEventStreamContext<Events>()

Then finally, add the Provider to your app.

import { EventStreamContext } from './streamConfig'

const App = () => {
  return (
    <EventStreamContext.Provider value={stream}>
      {/* my phenomenal app goes here */}
    </EventStreamContext.Provider>
  )
}

Subscribing

import { useStreamCallback } from '@twopm/use-stream'
import { EventStreamContext } from './streamConfig'
import { filter } from 'rxjs/operators'

export const ClickTracker = () => {
  const [clicks, setClicks] = useState(0)

  useStreamCallback(
    EventStreamContext,
    s =>
      s
        .pipe(
          filter(x => x.type === 'mouseClicked'),
        )
        .subscribe(_ => {
          setClicks(clicks + 1)
        }),
    [clicks, setClicks]
  )

  return <div>Clicked: {clicks} times</div>
}

Emitting

import { useEmit } from '@twopm/use-stream'
import { EventStreamContext } from './streamConfig'

export const ClickEmitter = () => {
  const emit = useEmit(EventStreamContext)
  const onClick = () => emit({ type: 'mouseClicked' })

  return <button onClick={onClick}>Click Me!</button>
}

Running this repo

Bootstrap

yarn
yarn bootstrap

Running the examples

cd packages/use-stream
yarn build
cd ../example
yarn start
0.0.7

4 years ago

0.0.5

4 years ago

0.0.6

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago