LoginSignup
24
21

More than 5 years have passed since last update.

react-dispatcher-decorator で PubSub な Flux

Last updated at Posted at 2016-06-24

react-dispatcher-decorator というのを作った

npm install react-dispatcher-decorator --save

コンセプト

昔作ったArdaのPubSub部分をDecoratorで表現した。https://github.com/mizchi/arda

この2つを使ってバケツリレーを隠蔽することで、デコレータでPub側とSub側を自然に繋げられるようにした。

hokaccha/react-micro-container: Micro framework for React も多少参考にした。

Example

import React from "react";
import {dispatcher, subscriber} from "react-dispatcher-decorator";

// This component subscribes events from child components by context
@subscriber((self, subscribe) => {
  subscribe('foo', (prop) => {
    console.log('foo received with', prop);
  });
})
class App extends React.Component {
  render() {
    return <Child/>
  }
}

// This component has this.context.dispatch and it will dispatch to parent subscriber
@dispatcher
class Child extends React.Component {
  render() {
    return <button onClick={() => this.context.dispatch('foo', 1)}>hello</button>
  }
}

import ReactDOM from "react-dom";
const el = document.querySelector(".main");
ReactDOM.render(<App/>, el);

Pub側で@subscriberデコレータを宣言しながらエミッターを初期化する。意図的に動的には生やしたりはできないようにしている。

@dipatcher が付与されたComponentの this.context.dispatch は自分の@subscribeデコレータを持つ親(何層上でもおk)のsubscribeを発火させる。

with PromisedReducer

これも自作のライブラリだけど、

を使うと、こんな感じになる。

import React from "react";
import {dispatcher, subscriber} from "react-dispatcher-decorator";
import PromisedReducer from "promised-ruducer";

@subscriber((self, subscribe) => {
  const reducer = new PromisedReducer({count: 0});
  reducer.on(":update", state => self.setState(state)); 
  subscribe('increment', (prop) => {
    reducer.update(state => ({count: state.count + 1}));
  });
})
class App extends React.Component {
  render() {
    return <Child count={this.state.count}/>
  }
}

// This component has this.context.dispatch and it will dispatch to parent subscriber
@dispatcher
class Child extends React.Component {
  render() {
    return <button onClick={() => this.context.dispatch('increment')}> {this.props.count} </button>
  }
}

// 略

PromisedReducer はこれまた自分が作った https://github.com/mizchi/flumpt の非同期更新のバッチ処理を最適化する部分を抜き出したもので、要はこの例はFlumptを小さいパーツに分解してデコレータ構文に糖衣して再構築するとこうなる、というもの。

flumpt はSSR対応してなかったんだけど、仕組み上だるかったので、SSRしたいならこういうアプローチでいけるはず。

24
21
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
21