Skip to content
This repository has been archived by the owner on Dec 26, 2022. It is now read-only.

bkonkle/stateful-wonka

Repository files navigation

Stateful Wonka

Minimal state management using Wonka's flexible streams.

  • When using with ReasonML, you can use ADT's and pattern matching to ensure you are exhuastively handing all possible actions.
  • When using with TypeScript, you can still gain strong type-safety by using enum properties on an object instead.

This library is written in Reason, a dialect of OCaml, and can be used for native applications. It is also compiled using BuckleScript to plain JavaScript and has bindings for TypeScript.

This means that out of the box this library is usable in any project that use the following:

  • Plain JavaScript
  • TypeScript
  • Reason/OCaml with BuckleScript
  • Reason/OCaml with bs-native
  • Reason/OCaml with Dune and Esy

Why?

To take advantage of Wonka's simple stream-based API to handle a variety of different kinds of async actions.

Installation

In JavaScript or TypeScript:

yarn install stateful-wonka

To use with Reason/OCaml with BuckleScript, add it to your bsconfig.json:

{
  // ...
  "bs-dependencies": ["wonka", "stateful-wonka"],
  // ...
}

Usage

Reducer

ReasonML

With ReasonML, you can use ADT's to eliminate the need for action types.

First, define a type to represent your state:

type state = {count: int}

Define an action type:

type action =
  | Increment
  | Double
  | Square;

Create your reducer:

let reducer =
  (. state, action) =>
    switch (action) {
    | Increment => {count: state.count + 1}
    | Double => {count: state.count * 2}
    | Square => {count: state.count * state.count}
    };

To use it, create a dispatcher:

open StatefulWonka.Reducer;

let dispatch = reduce(reducer, initialState);

The dispatcher is a Wonka Operator, and it can be subscribed to using any kind of Sink.

open StatefulWonka.Reducer;
open Wonka;

makeAsyncAction(source => source |> getItemFromApi |> map(addItemToItems))
|> dispatch
|> toPromise;

TypeScript

First, define a type to represent your state:

interface State = {count: number}

Then, define your action types enum:

enum Actions {
  Increment,
  Double,
  Square,
}

Define an action type:

interface Action = {type: Actions}

Finally, create your reducer:

const reducer = (state: State, action: Action) => {
  switch (action.type) {
    case Actions.Increment:
      return {...state, count: state.count + 1}
    case Actions.Double:
      return {...state, count: state.count * 2}
    case Actions.Square:
      return {...state, count: state.count * state.count}
    default:
      return state
  }
}

To use it, create a dispatcher:

import {reduce} from 'stateful-wonka'

const dispatch = reduce(reducer, initialState)

The dispatcher is a Wonka Operator, and it can be subscribed to using any kind of Sink.

await pipe(
  makePromiseAction(getItemFromApi.then(addItemToItems)),
  dispatch,
  toPromise
)

About

State management based on Wonka streams

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published