Fluxxor を使っていると次のようなエラーに出くわすことがある。
Uncaught Error: Could not find flux on this.props or this.context of XXXX
Fluxxor によって作られる Flux フローに関連するコンポーネント (React) は、Fluxxor Flux インスタンスを持っている必要があるが、これが見つからないと言われてしまっている。
原因
簡単に言うと、FluxMixin されたコンポーネントにおいて本来であれば render() で生成される子コンポーネントに対して自動的に Flux インスタンスが付与される処理が盛り込まれているが、それ以外の方法で生成されたコンポーネントにはそれがなされないから。
例
比較的キャッチーな React Bootstrap の Modal component を用意した。
var MyModal = React.createClass({
mixins: [ FluxMixin ],
render: function() {
return (
<Modal {...this.props} title="Modal heading" animation={false}>
<div className="modal-body">
<h4>Text in a modal</h4>
</div>
</Modal>
);
},
// ...
});
var ModalTrigger = React.createClass({
mixins: [ FluxMixin ],
render: function() {
return (
<ModalTrigger modal={<MyModal />}>
<Button bsStyle="primary" bsSize="large">Launch demo modal</Button>
</ModalTrigger>
);
},
// ...
});
var flux = new Fluxxor.Flux(stores, actions);
React.render(<ModalTrigger flux={flux} />, document.getElementById("open-modal"));
細かな内容はさておき、上記コードを動かすと前述の Fluxxor エラーが MyModal に対して発生する。MyModal の生成が ModalTrigger によって行われているため。
なので、同一の Flux インスタンスをコンポーネント生成時に渡すようにしてしまえばいい。
var ModalTrigger = React.createClass({
mixins: [ FluxMixin ],
render: function() {
var flux = this.getFlux();
return (
<ModalTrigger modal={<MyModal flux={flux} />}>
<Button bsStyle="primary" bsSize="large">Launch demo modal</Button>
</ModalTrigger>
);
},
// ...
});
まとめ
特定の振る舞いをしたりコンポーネントを生成したりする Mixin を使っていたりすると、どこかで親子関係による Flux インスタンスのチェーンが切れてしまってこの状況になることが多そう。
なので、上記例のように関係が切れてしまいそうな箇所で落ち着いて getFlux() して生成されるコンポーネントのプロパティに渡してあげる。