Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

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

非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は色んな物を隠蔽しすぎてサーバーサイドレンダリングに対応できてないので、これぐらいが適当な気がする。

plaid
CXプラットフォーム「KARTE」の開発・運営、EC特化型メディア「Shopping Tribe」の企画・運営、CX特化型メディア「XD(クロスディー)」の企画・運営
https://plaid.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした