web-dev-qa-db-ja.com

取得方法:レンダリング後のコンポーネントの幅React

他のアプリケーションで再利用できる汎用コンポーネントを作成しようとしています。コンポーネントのコンテンツを変更できるように、レンダリング後のコンポーネントの幅を知る必要があります。

私はさまざまなライフサイクルを使用して、成功せずに反応してみました。

componentDidUpdate() {
  console.log('width', this.element.offsetWidth);
}

render() {
  return (
    <div ref={(element) => {this.element = element }} />
  );
}

これを試すと画面の幅が表示されますが、ウィンドウのサイズを変更すると、コンポーネントの幅が表示されます。 Chrome Log:

Chrome log

ComponentDidMountはレンダリングの前に実行されるので、this.elementundefinedです。

また、npmのさまざまなライブラリを使用して、運が悪ければこれを解決しようとしました。

詳細情報:コンポーネントは、Bootstrap列内で異なる幅で機能する必要があります。

render() {
  <Row>
    <Col sm={3} />
      <MyComponent />
    </Col>
    <Col sm={9} />
      <MyComponent />
    </Col>
  <Row>
}

説明ウィンドウのサイズを変更したくありません。わかりづらいことをお詫びします。サイズ変更について言及する唯一の理由は、DOMが作成されてサイズを変更すると、offsetWidthに正しい値が表示されることです。サイズを変更せずに正しい値を取得するソリューションを探しています。レンダリング後の関数呼び出し、リスナー、いくつかの反応魔法、または他のソリューションのいずれか。私の問題は、仮想DOMと実際のDOMに関する知識の欠如です。

4
R. Gulbrandsen

私はここに与えられた答えでこの問題を解決することができませんでした。ブラウザーウィンドウの幅のみを取得し、内部のコンポーネントは取得しませんでした。いくつかの調査の結果、レンダリングで鶏または卵の問題が発生しているようです。さらに調査した結果、react-sizeme問題を解決します。

import React, { Component } from 'react';
import sizeMe from 'react-sizeme';

class MyComponent extends Component {
  render() {
    const { width } = this.props.size;

    return (
      <div style={{
        width: '100%',
        backgroundColor: '#eee',
        textAlign: 'center'
      }}>
        <span>My width is: {Math.floor(width)}px</span>
      </div>
    );
  }
}

export default sizeMe()(MyComponent);

最初にレンダリングしたときに次のものが生成されます

enter image description here

2
R. Gulbrandsen

コンポーネントの幅の状態を保持する必要がある場合は、次のようなことができます。

componentDidMount(){ 

          this.boundingBox = this.element.getBoundingClientRect();

          this.setState({ 
              width:this.boundingBox.width
          }); 

          Observable.fromEvent(this.element,"resize")
          .subscribe(
              () => { 
                this.boundingBox = this.element.getBoundingClientRect();  
                this.setState({ 
                    width:this.boundingBox.width
                }); 
              }
          );

};    

Observableをイベントリスナーに置き換えることができます。または、クラスにアタッチされたバウンディングボックスを更新して、別の場所から状態を派生させることもできます。

componentDidUpdate(){ 
          this.boundingBox = this.element.getBoundingClientRect();
};     

これはあなたの質問に対する直接の回答ではありませんが、コンポーネント内にサイズ変更やダーティロジックを追加しない問題の解決策です

https://github.com/digidem/react-dimensions -これはHOCラッパーであり、グローバルサイズ変更イベントをリッスンして小道具を送信します-containerWidthおよびcontainerHeight-SVG、キャンバス、およびデータグリッドを反応させて応答性を維持し、要素のサイズを知る必要がある場合、私はそれを頻繁に使用する傾向があります。

ライフサイクルに関しては-componentDidUpdateのようなものはあなたが思っているように動作しないかもしれません。マウントは1回限りです。このコメントを読む- https://github.com/facebook/react/issues/2659#issuecomment-66165159

1