Skip to content

Commit 38c5c05

Browse files
committed
update readme with new counter example
1 parent 42cdcb6 commit 38c5c05

File tree

3 files changed

+74
-126
lines changed

3 files changed

+74
-126
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,5 @@ deploy.pub
4343
/history.js
4444
/test-utils.js
4545
public/app.js
46+
gh-pages/
47+
wiki/

README.md

Lines changed: 70 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,104 @@
1-
# React Most
1+
# -⚛-> React Most
22

33
[![Join the chat at https://gitter.im/jcouyang/react-most](https://badges.gitter.im/jcouyang/react-most.svg)](https://gitter.im/jcouyang/react-most?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
44

5-
A Monadic Reactive State Container for React Components
5+
A Monadic Reactive Composable State Wrapper for React Component
66

77
[![CircleCI](https://circleci.com/gh/reactive-react/react-most.svg?style=svg)](https://circleci.com/gh/reactive-react/react-most)
88
[![codecov](https://codecov.io/gh/reactive-react/react-most/branch/master/graph/badge.svg)](https://codecov.io/gh/reactive-react/react-most)
99
[![npm](https://img.shields.io/npm/dm/react-most.svg?maxAge=2592000)](https://www.npmjs.com/package/react-most)
1010
[![npm](https://img.shields.io/npm/v/react-most.svg?maxAge=2592000)]()
1111

12+
## Install
1213
```
1314
npm install react-most --save
1415
```
1516

16-
<!-- TOC depthFrom:1 depthTo:2 withLinks:1 updateOnSave:1 orderedList:0 -->
17-
18-
- [React Most](#react-most)
19-
- [What](#what)
20-
- [Why not (just using existing state container e.g.) redux](#why-not-just-using-existing-state-container-eg-redux)
21-
- [Why indeed?](#why-indeed)
22-
- [How](#how)
23-
- [[API](https://github.com/jcouyang/react-most/wiki/API)](#apihttpsgithubcomjcouyangreact-mostwikiapi)
24-
- [[More Examples](./examples)](#more-examplesexamples)
25-
- [Performance](#performance)
26-
- [Thanks to...](#thanks-to)
27-
28-
<!-- /TOC -->
29-
3017
## What
31-
`most.js` is very high performance Monadic reactive streams lib. Rich User Interaction App is natively fit Reactive Programming pretty well.
32-
33-
`React` is awesome for writing UI Components.
34-
35-
So, what `react-most` does is simply making you React Components Reactive.
36-
37-
`react-most` is simple and only 90 lines of code. only depends on most and react.
18+
`react-most` is simple and only 100 LOC React Higher Order Component. only depends on most and react.
3819

3920
data flow is simple and one way only
4021
![](https://raw.githubusercontent.com/jcouyang/react-most/master/docs/images/flow.dot.png)
4122

42-
- **Action** will generate value and add it into `Intent Stream`
43-
- **Sink** create new Stream based on action type in `Intent Stream`
44-
- **Sink** transform a value Stream into a `oldState=>newState` mapping Stream
45-
- **State** subscribe to **Sinks** changes
23+
## Terminology
24+
- **Action**: a action can create a Intent and send to `Intent Stream`
25+
- **Intent Stream**: a time line of all kinds of `Intent` created by `Action`
26+
- **Sink** a time line of transforms of state e.g.`--- currentState => nextState --->`
27+
- **State** simply a react component state
4628

29+
## Quick Start
4730

48-
## Why not (just using existing state container e.g.) redux
49-
When I play around with redux, it's awesome but
31+
sorry we don't have a **book** to document how to use `react-most`, and I don't really need to, but
32+
there's only 3 things you should notice when using `react-most`, I'll explain by a simple counter app.
5033

51-
1. it take little time to make it ready.
52-
2. it's using too many concept that we probably don't even care, which make it's learning curve a little steep(it take a [gitbook](http://rackt.org/redux/index.html) to document just a state container?)
53-
3. Reducers (long switch statements which are syntactically ugly but semantically ok) -- Andre
54-
4. component is not composable, action is not composable, component and behaviour shouldn't be so tight coupling。
34+
also you can refer to various of [Examples](https://github.com/reactive-react/react-most/wiki/examples.md) and it's simple [API](https://github.com/reactive-react/react-most/wiki/api.md)
35+
36+
### 1. Create a simple statless component
37+
```html
38+
const CounterView = props => (
39+
<div>
40+
<button onClick={props.actions.dec}>-</button>
41+
<span>{props.count}</span>
42+
<button onClick={props.actions.inc}>+</button>
43+
</div>
44+
)
45+
```
46+
### 2. Define Counter's Behaviour
47+
1. a counter can have actions of `inc` and `dec`, which will send a objec `{type: 'inc'}` or `{type:'dec'}` to `Intent Stream` if it's been call
48+
2. a counter reactivly generate state transform function when recieve intent of type `inc` or `dec`.
49+
```js
50+
const counterable = connect(intent$ => {
51+
return {
52+
actions: {
53+
inc: () => ({ type: 'inc' }),
54+
dec: () => ({ type: 'dec' }),
55+
},
56+
sink$: intent$.map(intent => {
57+
switch (intent.type) {
58+
case 'inc':
59+
return state => ({ count: state.count + 1 });
60+
case 'dec':
61+
return state => ({ count: state.count - 1 });
62+
default:
63+
return _ => _;
64+
}
65+
}),
66+
}
67+
})
68+
```
69+
### 3. connect behaviour and view
5570

56-
again, I couldn't agree more on Andre's [article about react/redux](http://staltz.com/why-react-redux-is-an-inferior-paradigm.html).
71+
```js
72+
const Counter = counterable(CounterView)
5773

58-
Inspired by Reactive Programming, Cycle.js and Redux, we can do something better to reduce the complexity of managing react state, the reactive way, by only introduce a little bit of reactive programming concepts.
74+
render(
75+
<Most>
76+
<Counter />
77+
</Most>
78+
, document.getElementById('app'));
79+
```
5980

60-
## Why indeed?
81+
## Features
6182

62-
Redux is awesome, but if you're big fan of Functional Reactive Programming, you would've imaged all user events, actions and data are Streams, then we can map,filter, compose, join those streams to React state.
83+
Redux is awesome, but if you're big fan of Functional Reactive Programming, you would've imaged all user events, actions and data are Streams, then we can map,filter, compose, join on those streams to React state.
6384

6485
### Pure Functional, Declarative & Monadic
6586
finstead of imperative describe what you want to do with data at certain step, we simple define data transforms and compose them to data flow. No variable, no state, no side effort at all while you composing data flow.
6687

6788
### Composable and Reusable Sinks
6889
sinks are composable and reusable, not like reducer in redux, where switch statement are hard to break and compose.
6990

70-
### Easy to Test
91+
also wrappers are simply function that you can easily compose
92+
```js
93+
const countBy1 = connect(...)
94+
const countBy2 = connect(...)
95+
const Counter = countBy1(countBy2(CounterView))
96+
// or
97+
const counterable = compose(counterBy1, counterBy2)
98+
const Counter = counterable(CounterView)
99+
```
100+
101+
### Easy to Test, no mocks
71102
since UI and UI behaviour are loose couple, you can simply define a dump react component and test it by passing data. seperatly you can test behaviour by given actions, and verify it's state.
72103

73104
```js
@@ -123,93 +154,8 @@ import rxEngine from 'react-most/engine/rx'
123154
</Most>
124155
```
125156

126-
## How
127-
128-
sorry we don't have a **book** to document how to use `react-most`, but
129-
there's only 3 things you should notice when using `react-most`, I'll explain by a simple counter app.
157+
## [More Documents...](https://github.com/jcouyang/react-most/wiki)
130158

131-
also you can refer to [API](./docs/api.md) or [Examples](#more-examples).
132-
133-
### 1. Component Wrapper
134-
```html
135-
import Most from 'react-most'
136-
<Most>
137-
<RxCounter />
138-
</Most>
139-
```
140-
### 2. Define How to connect Component and Streams
141-
142-
```js
143-
import {connect} from 'react-most'
144-
import most from 'most'
145-
const Counter = (props)=>{
146-
return <div>{props.value}</div>
147-
}
148-
let RxCounter = connect(function(intent$){
149-
let defaultState$ = most.of(_=>({value:0}))
150-
let addSink$ = intent$.filter(x=>x.type=='add').map(({increment})=>state=>({value: state.value+increment}))
151-
return {
152-
add: increment=>({type: 'add', increment}),
153-
defaultState$,
154-
addSink$,
155-
}
156-
})(Counter);
157-
```
158-
here are things you may need to pay attention to:
159-
160-
#### 2.1. transform intent stream to state mapper stream
161-
162-
the transformer accept a Intetent Stream `intent$`(by convention, all Stream type variable name with suffix $), and create and return new Intent Streams(here we call those new stream -- `sinks`)
163-
164-
```js
165-
let addSink$ = intent$.filter(x=>x.type=='add').map(({increment})=>state=>({value: state.value+increment}))
166-
```
167-
168-
here we filter out only `add` intent and do something about it.
169-
170-
when I mean something, I mean transform intent to be a state transformer. which means Intent Stream of **values**
171-
172-
--`{value: 1}`--`{value: 2}`--`{value:3}`-->
173-
174-
becomes a Stream of **functions** which tranform old state into new state
175-
176-
--`state=>({value: state.value+1})`--`state=>({value: state.value+2})`--`state=>({value: state.value+3})`-->
177-
178-
#### 2.2. define action mapper that can be use to added intent to your Intent Stream.
179-
180-
```js
181-
add: increment=>({type: 'add', increment}),
182-
```
183-
here it define a `add` action mapper, it define how you can use the action. it's pretty clear here that the search action will accept only one arg `increment`, and `{type: 'add', increment}` is something will be send to Intent Stream when action is called.
184-
185-
### 3. Use the actions
186-
like redux, but much simpler, when you wrap your App, your App get a `actions` props, and you can pass it all along to any child Component.
187-
188-
```js
189-
<button className="add1"
190-
type="checkbox"
191-
onClick={()=>this.props.actions.add(1)} />
192-
```
193-
194-
## [API](https://github.com/jcouyang/react-most/wiki/API)
195-
196-
## [More Examples](./examples)
197-
- [BMI Calculator](http://jsbin.com/bojaqiv/edit?js,output)
198-
- [Type N Search](./examples/type-n-search) [(live)](https://reactive-react.github.io/react-most/examples/type-n-search/public/)
199-
- [TodoMVC](./examples/todomvc) [(live)](https://reactive-react.github.io/react-most/examples/todomvc/public/)
200-
- [Type N Search with Transducers](./examples/transducer-type-n-search) [(live)](https://reactive-react.github.io/react-most/examples/transducer-type-n-search/public/)
201-
- [Type N Search with Time Travel](./examples/type-n-search-with-undo) [(live)](https://reactive-react.github.io/react-most/examples/type-n-search-with-undo/public/)
202-
203-
## Performance
204-
`react-most` no more than creating stream from your actions, and bind it to state stream. no any other computations happen in `react-most`. so please refer to [most.js's perf](https://github.com/cujojs/most/tree/master/test/perf) which is realy Great!
205-
206-
I also do a simple benchmark with 8k times of performing counter increase action
207-
```
208-
Memory Usage Before: { rss: 32501760, heapTotal: 16486912, heapUsed: 11307128 }
209-
Memory Usage After: { rss: 34418688, heapTotal: 18550784, heapUsed: 11932336 }
210-
Elapsed 8ms
211-
```
212-
basically the same level of performance as redux(which is 10ms in the same testing)
213159

214160
## Thanks to...
215161
- [most](https://github.com/cujojs/most)

examples/counter/src/app.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const CounterView = props => (
1212

1313
CounterView.defaultProps = { count: 0 };
1414

15-
const reactify = connect((intent$) => {
15+
const counterable = connect((intent$) => {
1616
return {
1717
sink$: intent$.map(intent => {
1818
switch (intent.type) {
@@ -29,7 +29,7 @@ const reactify = connect((intent$) => {
2929
}
3030
})
3131

32-
const Counter = reactify(CounterView)
32+
const Counter = counterable(CounterView)
3333

3434
render(
3535
<Most>

0 commit comments

Comments
 (0)