it-swarm.com.ru

Как получить: ширину компонента после рендеринга в React

Я пытаюсь создать компонент общего назначения, который я могу использовать в других приложениях. Мне нужно знать ширину компонента после рендера, чтобы я мог изменить содержимое компонента.

Я пытался использовать разные жизненные циклы в реакции без успеха.

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

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

Когда я пытаюсь это сделать, я получаю ширину экрана, но если я изменяю размер окна, я получаю ширину компонента. Смотрите Chrome Журнал:

Chrome log

ComponentDidMount выполняется перед рендерингом, поэтому this.element равен undefined.

Я также попытался использовать разные библиотеки из npm, чтобы решить эту проблему без удачи.

Дополнительная информация: Компонент должен работать внутри столбца Bootstrap с различной шириной.

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

Пояснение Я не хочу изменять размер окна, и я прошу прощения за то, что не ясно. Единственная причина, по которой я могу упомянуть изменение размера, заключается в том, что когда DOM был создан и я изменил размер, я получил правильное значение в offsetWidth. Я ищу решение, где я получаю правильное значение без изменения размера. Либо вызов функции пост-рендеринга, слушатели, некоторые реагируют на магию или другие решения. Моя проблема в том, что у меня нет знаний о виртуальном и реальном DOM.

3
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();
};     
1
Anatoly Strashkevich

Принимая во внимание, что это не ответ на ваш вопрос напрямую, это решение вашей проблемы, которое не добавляет изменения размера и грязную логику внутри ваших компонентов. 

Я бы порекомендовал что-то вроде https://github.com/digidem/react-dimensions - который является оболочкой HOC и будет прослушивать глобальные события изменения размера и отправлять вам реквизиты - containerWidth и containerHeight - Я склонен использовать это Многое при работе с SVG, холстом и сетками данных в реакции, которые должны оставаться отзывчивыми и знать размер элемента. 

Что касается жизненных циклов - такие вещи, как componentDidUpdate, могут вести себя не так, как вы думаете. Маунт одноразовый. Прочитайте этот комментарий - https://github.com/facebook/react/issues/2659#issuecomment-66165159

0
Dimitar Christoff