94
88

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

EventEmitterバケツリレースタイル/フレームワークなしで小さくFluxする

Last updated at Posted at 2016-03-11

想定しているシチュエーション

非SPA環境で個別にマウントされるコンポーネントがそれぞれで小さくFluxするような環境。

SPAガッツリ組むのでないなら、Fluxフレームワークは不要だと思っていて、とは言えオレオレ構成も行き過ぎると害になる。
その辺のバランスをとって、次のような構成がいいのではないか、と考えてみた。

考え方

  • コンテナがEventEmitterを1つ保持する
  • コンテナはEventEmitterの各種イベントをListenする
  • コンテナはpropsとstateを区別して扱い、stateを更新する
  • コンテナはコンポーネントを一つだけ描画する
  • コンポーネントはpropsとして渡されたEventEmitterを発火させる
  • コンポーネントはEventEmitterをListenしない
  • コンポーネントはpropsのみ扱う

コード

// src/components/header.js
export default ({title, emitter}) => (
  <header>
    <h1 onClick={e => emitter.emit("changeTitleToBar")}>{title}</h1>
  </header>
);

// src/containers/header-container.js
import Header from "../components/header";
import {Component} from "react";
import {EventEmitter} from "events";

export default class HeaderContainer extends Component {
  constructor(props) {
    super(props);
    this.state = {title: "foo"};
    this.emitter = new EventEmitter;

    // EventEmitter の PubSub
    // 親の責務は setState/replaceState で State 更新
    // ここを Atomic にしないと完全に見失う
    this.emitter.on("changeTitleToBar", () => {
      this.replaceState({title: "bar"});
    });
  }
  render(){
    // 適当にマッピングして子に渡す
    return <Header ...{Object.assign({}, this.props, this.state, {emitter: this.emitter})}/>
  }
}
// src/main.js
import HeaderContainer from "./containers/header-container";
import ReactDOM from "react-dom";
ReactDOM.render(<HeaderContainer />, document.querySelector(".headerContainer"));

利点

  • 導入が簡単
  • フレームワークで隠蔽する箇所が無いので、読みやすい

欠点

  • emitterを全ての子Componentにバケツリレーする必要がある
  • なんでもできて割れ窓っぽい

改善案としては

    return <Header ...{Object.assign({}, this.props, this.state, {dispatch: this.emitter.emit.bind(this.emitter)})}/>

などとすると 発火の関数だけ渡すと 子がlisten できなくなる

運用してみたか

いいえ。

とはいえ https://github.com/mizchi/flumpt は、この発想を Reactのcontextという機能を使ってemitterバケツリレーを隠蔽し、それにアクセスするDSLを足しただけ。

ただflumptは色んな物を隠蔽しすぎてサーバーサイドレンダリングに対応できてないので、これぐらいが適当な気がする。

94
88
0

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
94
88

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?