Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
88
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

@mizchi

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

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

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

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
88
Help us understand the problem. What are the problem?