Git Product home page Git Product logo

react-most's Introduction

-:atom_symbol:-> React Most

Join the chat at https://gitter.im/jcouyang/react-most

A Monadic Reactive Composable State Wrapper for React Components

CircleCI codecov npm npm greenkeeper.io

Install

npm

npm install react-most --save

browser

<script src="https://cdn.rawgit.com/reactive-react/react-most/master/dist/vendor.js"></script>
<!-- vendor.js includes react, most, most-subject -->
<script src="https://cdn.rawgit.com/reactive-react/react-most/master/dist/react-most.js"></script>

then you can use Most.default and Most.connect

What

react-most is a simple, 100 LOC Higher Order Component for React. Its only dependencies are most, most-subject, ramda, React, and (optionally, if you prefered) RxJS.

Data flow in react-most is simple and unidirectional.

Terminology

  • Action: an Action can create an Intent and send it to the Intent Stream

  • Intent Stream: a timeline of every Intent created by every Action

  • Sink: a timeline of transformations of state, e.g.

      --- (currentState => nextState) -- (currentState => nextState) --->
    
  • State: a React component's state

Quick Start

sorry we don't have a book to document how to use react-most, and I don't really need to, but there's only 3 things you should notice when using react-most, I'll explain by a simple counter app.

Also, you can refer to:

1. Create a simple stateless component

const CounterView = props => (
  <div>
    <button onClick={props.actions.dec}>-</button>
    <span>{props.count}</span>
    <button onClick={props.actions.inc}>+</button>
  </div>
)

2. Define Counter's behavior

  1. A counter can have actions of inc and dec, which will send either {type: 'inc'} or {type:'dec'} to Intent Stream upon being called.
  2. A counter reactively generates a state transformation function when it receives an Intent of either type inc or dec.
const counterable = connect((intent$) => {
  return {
    sink$: intent$.map(intent => {
      switch (intent.type) {
        case 'inc':
          return state => ({ count: state.count + 1 });
        case 'dec':
          return state => ({ count: state.count - 1 });
        default:
          return _ => _;
      }
    }),
    inc: () => ({ type: 'inc' }),
    dec: () => ({ type: 'dec' })
  }
})

3. Connect behavior and view

const Counter = counterable(CounterView)

render(
  <Most>
    <Counter />
  </Most>,
  document.getElementById('app')
);

Features

Inspired by Redux and Functional Reactive Programming, react-most allows you to model user events, actions, and data as reactive streams. Now you can map, filter, compose, and join those streams to form your application's state.

Purely Functional, Declarative, and Monadic

In imperatively written code, you describe step-by-step how to process data. With react-most, we simply define data transformations, then compose them to form our data flow. There are no variables, no intermediate state, and no side effects in your data flow's data composition!

Composable and Reusable Sinks

In Redux, reducers' use of switch statements can make them difficult to compose. Unlike reducers, sinks are reusable observable object.

Wrapper is simply a function and easily composable.

const countBy1 = connect(...)
const countBy2 = connect(...)
const Counter = countBy1(countBy2(CounterView))
// or
const counterable = compose(countBy1, countBy2)
const Counter = counterable(CounterView)

Easy to test, no need for mocks

Because UI and UI behavior are loosely coupled, you can test a React component by just passing it data. Behaviors can be tested by calling actions and then verifying the state.

import {stateHistoryOf, Engine } from 'react-most-spec';
let counterWrapper = TestUtils.renderIntoDocument(
        <Most engine={Engine}>
          <Counter history={true} />
        </Most>
)
let counter = TestUtils.findRenderedComponentWithType(counterWrapper, Counter)
counter.actions.inc()
counter.actions.inc()
counter.actions.inc()
expect(stateHistoryOf(counter)[2].count).toBe(3)

see more details about testing at react-most-spec or todomvc example

Async actions

Asynchronous functions, such as Promises, can be converted to a stream and then flat-mapped.

intent$.map(promise => most.fromPromise(promise))
	.flatMap(value => /* use the results */)

Transducers support

Transducer is another high-performance, functional way to compose non-monadic data flows.

Writing actions as transducers can improve reusability.

Time Travel

Because we have all actions' streams, we can easily reproduce the actions at anytime, or get snapshot of the state's stream and going back in time.

By passing the history parameter into the options of connect

connect(intent$=>[/* your awesome flow */], { history: true })(App)

or passing history as a prop

<Most>
  <Counter history={true}/>
</Most>

A stream with all of the state's history will be created, called historyStream.

Modular and Easy to Extend

If you're more familiar with RxJS, it's easy to use it with react-most in place of most. Simply pass a prop called engine to the Most component.

But, I'm strongly RECOMMEND to use the default engine most.js, it's how react-most originally built for, and production ready.

import rxEngine from 'react-most/engine/rx'
<Most engine={rxEngine}>
  <App />
</Most>

Thanks to...

react-most's People

Contributors

jcouyang avatar greenkeeper[bot] avatar kaichaosun avatar troutzen avatar r3d4c73d avatar gitter-badger avatar melonq avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.