5

独自の 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 がトリガーされ、コンポーネントがまだ使用されている間にコンポーネントをアンマウントするために呼び出されます。それは機能しますが、醜いです。handleSelectionChangeremove()

より良い、より慣用的な方法はありますか?

4

1 に答える 1