web-dev-qa-db-fra.com

Comment obtenir: Largeur du composant après rendu dans React

J'essaie de créer un composant à usage général, que je peux réutiliser dans d'autres applications. J'ai besoin de connaître la largeur du composant après le rendu pour pouvoir en modifier le contenu.

J'ai essayé d'utiliser les différents cycles de vie pour réagir sans succès.

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

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

Quand j'essaye ceci j'obtiens la largeur de l'écran, mais si je change la taille de la fenêtre, j'obtiens la largeur du composant. Voir le journal Chrome:

 Chrome log

ComponentDidMount s'exécute avant le rendu, donc this.element est undefined.

J'ai également essayé d'utiliser différentes bibliothèques de NPM pour résoudre ce problème sans succès.

Informations ultérieures: Le composant doit fonctionner dans une colonne Bootstrap, en différentes largeurs.

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

Clarification Je ne veux pas redimensionner la fenêtre et je m'excuse de ne pas être clair. La seule raison pour laquelle je mentionne le redimensionnement est que, lorsque le DOM est créé et que je redimensionne, la valeur correcte est donnée dans offsetWidth. Je recherche une solution permettant d'obtenir la valeur correcte sans redimensionnement. Soit un appel de fonction après rendu, des écouteurs, certains réagissent magiquement ou d’autres solutions. Mon problème est mon manque de connaissances avec le DOM virtuel vs réel.

3
R. Gulbrandsen

J'ai été incapable de résoudre ce problème avec les réponses données ici. Je n'ai que la largeur de la fenêtre du navigateur et non le composant qu'il contient. Après quelques recherches, il semble que je rencontre un problème avec le rendu du poulet ou de l'œuf. Après quelques recherches supplémentaires, j'ai trouvé react-sizeme qui résout le problème.

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);

Ce qui produira ce qui suit lors du premier rendu

 enter image description here

2
R. Gulbrandsen

Si vous devez conserver l'état de la largeur du composant, vous pouvez faire quelque chose comme ceci:

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
                }); 
              }
          );

};    

Vous pouvez remplacer Observable avec un écouteur d'événement. Vous pouvez également mettre à jour le cadre de sélection attaché à la classe et en extraire l’état ailleurs.

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

Tandis que ceci n'est pas une réponse directe à votre question, c'est une solution à votre problème qui n'ajoute pas de logique de redimensionnement et sale à l'intérieur de vos composants. 

Je recommanderais quelque chose comme https://github.com/digidem/react-dimensions - qui est un wrapper HOC et qui écoutera les événements de redimensionnement global et vous enverra des accessoires - containerWidth et containerHeight - j'ai tendance à l'utiliser En travaillant avec SVG, la grille et les grilles de données réagissent souvent de manière à rester réactifs et à connaître la taille de l'élément. 

En ce qui concerne les cycles de vie, des éléments tels que componentDidUpdate peuvent ne pas se comporter comme vous le pensez. Mount est une pièce unique. Lire ce commentaire - https://github.com/facebook/react/issues/2659#issuecomment-66165159

0
Dimitar Christoff