独自の DOM ツリーの子ではないサブコンポーネントを管理する必要があるが、最上位のドキュメントに追加する必要があるコンポーネントを考えてみましょう。
典型的な例は、入力フィールドの下のフローティング メニューにオートコンプリートの一致を表示する必要があるオートコンプリート フィールドです。フローティング メニューは、表示を妨げるツリー内の "overflow: hidden" 制約を回避するために、必ずドキュメント body 要素の子として追加する必要があります。フローティング メニューは、使用されなくなったら削除する必要があります。
このような場合、論理的なアプローチは、コンポーネントを任意の div にマウントし、後で不要になったときにアンマウントすることです。ただし、イベントを使用してそのようなアンマウントをトリガーすると、興味深い状態フローの問題が発生します。
問題を説明するために、現在のコードからの抜粋を次に示します。
componentDidUpdate: function(prevProps, prevState) {
if (prevState.matches !== this.state.matches) {
if (this._floater) {
this._floater.remove();
this._floater = null;
}
if (this.state.matches.length > 0) {
this._floater = Floater.create(
<Floater
parentElement={this.getDOMNode()}
open={true}>
<SelectableList
items={this.state.matches}
limit={10}
onSelectionChange={this.handleSelectionChange}/>
</Floater>
);
}
}
},
handleSelectionChange: function(items) {
this.setState({matches: [], selectedItem: items[0]});
},
ここでFloater
は、他のコンポーネントを含むことができる汎用コンポーネントです。自分自身を絶対に設定し、自分自身を配置します。Floater.create()
floater コンポーネントを作成してドキュメントに挿入する便利なメソッドです。
Floater.remove()
現在、次のようになっています。
remove: function() {
var self = this;
if (this.isMounted()) {
window.setTimeout(function() {
React.unmountComponentAtNode(self.getDOMNode().parentNode);
}, 10);
}
},
タイムアウトを使用する理由は、親コンポーネントが状態の更新後にリモートにできるようにするためです。で何かを選択すると、親でSelectableList
がトリガーされ、コンポーネントがまだ使用されている間にコンポーネントをアンマウントするために呼び出されます。それは機能しますが、醜いです。handleSelectionChange
remove()
より良い、より慣用的な方法はありますか?