Skip to content

lukevmorris/tube

 
 

Repository files navigation

Tube

Easy state management for React, inspired by Redux and ember-concurrency.

Features:

  • Single source of truth
  • Immutable state updates / event sourcing pattern
  • Powerful concurrency primitives
  • Derived state (no more isLoading bookkeeping)
  • In-progress task cancellation
  • Made for TypeScript

Design goals:

  • Ease of use
  • Lack of boilerplate
  • Testable API design

Installation

npm install @chnn/tube

Quickstart

Define your application state and initialize Tube's task and connect utilities:

// src/store.tsx

import initalize from "@chnn/tube"

interface AppState {
  count: number
}

const initialState: AppState = { count: 0 }

export const { task, connect } = initialize<AppState>(initialState)

Then connect components to your application state using task and connect:

// src/counter.tsx

import * as React from 'react'
import {TaskProp} from '@chnn/tube'

import * as api from "./api"
import { AppState, connect, task } from "./store"

interface Props {
  count: number
  onIncrement: TaskProp
}

const Counter: React.SFC<Props> = ({ count, onIncrement }) => (
  <div className="counter">
    <div className="value">
      Value: {onIncrement.isRunning ? <div className="loader" /> : count}
    </div>
    <button onClick={onIncrement}>+ Add 1</button>
  </div>
)

const increment = task(function*(getState) {
  const x = yield api.getCount(1) // Returns 1 after one second

  return { count: getState().count + x }
}).restartable()

const mapStateToProps = (state: AppState) => ({
  count: state.count
})

const mapTasksToProps = {
  onIncrement: increment
}

export default connect(
  mapStateToProps,
  mapTasksToProps,
  Counter
)

You can run this example yourself.

About

Easy state management for React

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 97.3%
  • JavaScript 2.7%