bit-shifter / transdux

managing React states with pubsub channel and transducers

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Transdux

https://badges.gitter.im/Join%20Chat.svg

https://circleci.com/gh/jcouyang/transdux.svg?style=svg

>中文<

Finnally a flux like framework don’t even need a tutorial.

Managing React Component state in Elegant & Functional way with transducers and channels from ClojureScript

Rationale

flux and redux are great and solve state management and communication pretty well.

But they are too complicated, users have to know toomany things about store, dispatcher, actions which they shouldn’t

In reality what we have to do is actually just need to talk to whatever component I like and get my state from one source of truth, so the simplest way to do this is:

For component who has actions, only thing it have to define is what can it do.

For component who want to call other component’s action, it directly dispatch a message to that component.

SO, all user have to know is how to define actions and dispatch messages.

The Big Picture https://www.evernote.com/l/ABe_8eE6o2dGlZMCmNnBap_fXy83GvJe6gcB/image.jpg

We’re using Channels/Actors Model from Clojure – core.async, It’s compile to JS by conjs

Basic Idea we composed channels, subs, pubs, and transducers together like tunnels, every message goes through the tunnel will got process by the transducer with action function user provided.

so, whenever a message is dispatch to input channel, you’ll get new state from the corresponding output channel. you don’t need to care about how the dispatching really happen in the framework.

Install

In your React project

npm install transdux --save

Usage

to wire in transdux, only 4 place you have to pay attention to.

1. wrap you app with Transdux

<Transdux>
  <App/>
</Transdux>

2. define what your component can do

// MainSection.jsx
let actions = {
  complete(msg, state){
    return {
      todos:state.todos.map(todo=>{
        if(todo.id==msg.id)
          todo.completed = !todo.completed
        return todo
      })
    }
  },
  clear(msg,state){
    return {
      todos: state.todos.filter(todo=>todo.completed==false)
    }
  }
}

3. mixin Transdux Mixin and Bind Actions

// MainSection.jsx
  import {TxMixin} from 'transdux'
  let MainSection = React.createClass({
    mixins: [TxMixin],
    componentDidMount(){
      this.bindActions(actions)
    },
    ...
  })

4. mixin and dispatch a message

//TodoItem.jsx
import MainSection from './MainSection'
let TodoItem = React.createClass({
    mixins: [TxMixin],
    render(){
        <input className="toggle"
            type="checkbox"
            checked={todo.completed}
            onChange={() => this.dispatch(MainSection, 'complete',{id:todo.id})} />

    }
})

Examples

see ./examples

Performance

for dispatching 1023 message at the same time, here is the Memory Usage and Time elapsed

tested on Macbook Pro 13, CPU 2.9GHz Intel Core i5, Mem 16GB 1867MHz DDR3

transdux

Memory Usage Before: { rss: 43307008, heapTotal: 18550784, heapUsed: 11889192 }
Memory Usage After: { rss: 46444544, heapTotal: 30921984, heapUsed: 15307800 }
Elapsed 51ms

setTimeout

Memory Usage Before: { rss: 45432832, heapTotal: 17518848, heapUsed: 12664416 }
Memory Usage After: { rss: 46772224, heapTotal: 19570688, heapUsed: 10927824 }
Elapsed 7ms

redux

Memory Usage Before: { rss: 21647360, heapTotal: 9275392, heapUsed: 4559616 }
Memory Usage After: { rss: 22638592, heapTotal: 9275392, heapUsed: 5472112 }
Elapsed 4ms

Yeah, I know, it’s slower then redux, and I’m working on it. But, it’s not bad, it’s totally reasonable trade-off a little performance to get writing code which is more composable, reusable, testable, easy to reason about.

TODOS

./ROADMAP.org

About

managing React states with pubsub channel and transducers

License:Other


Languages

Language:JavaScript 93.5%Language:Shell 6.5%