React ref.current is null - PullRequest
       11

React ref.current is null

6 голосов
/ 19 марта 2019

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

Так, например: если повестка дня начинается с7 часов утра и заканчивается в 5 часов дня, общий диапазон составляет 10 часов.Допустим, тело календаря имеет высоту 1000 пикселей.Это означает, что каждый час означает 100 пикселей, а каждую минуту - 1,66 пикселей.

Если текущее время - 3 часа дня.У нас 480 минут с начала повестки дня.Это означает, что строка для отображения текущего времени должна находиться на расстоянии 796,8 пикселей (480 * 1,66) от верхней части тела календаря.

Нет проблем с расчетами, но с получением высотыповестка дня.Я думал использовать React Ref для получения высоты, но я получаю сообщение об ошибке: ref.current is null

Ниже некоторого кода:

class Calendar extends Component {
    calendarBodyRef = React.createRef();

    displayCurrentTimeLine = () => {
        const bodyHeight = this.calendarBodyRef.current.clientHeight; // current is null
    }

    render() {
        return (
            <table>
                <thead>{this.displayHeader()}</thead>
                <tbody ref={this.calendarBodyRef}>
                    {this.displayBody()}
                    {this.displayCurrentTimeLine()}
                </tbody>
            </table>
        );
    }
}

Ответы [ 2 ]

5 голосов
/ 19 марта 2019

Итак, суть ссылок в том, что они не гарантируются при первом рендере. Вы можете быть уверены, что они установлены во время и после componentDidMount, поэтому у вас есть два пути вперед.

Вы можете использовать стиль обратного вызова ref и установить состояние на его основе. Например. вместо того, чтобы передавать ваш ref как опору, вы можете передать ссылку на функцию, подобную this.handleRef, и она будет выполнять некоторую логику:

  handleRef = r => {
    this.setState({ bodyHeight: r.clientHeight})
    this.calendarBodyRef .current = r;
  };

Или вы можете сохранить текущую настройку, но вам придется переместить свой бит clientHeight в функцию жизненного цикла, например:

  componentDidMount() {
    this.setState({ bodyHeight: this.calendarBodyRef .current.clientHeight });
  }

В конечном счете, вы не можете сразу прочитать текущее значение ссылки, как это, вам придется проверить его после рендера, а затем прочитать bodyHeight из состояния.

0 голосов
/ 19 марта 2019

Если предпочтительнее избегать хранения вычисленной высоты тела в состоянии компонента, тогда другим подходом было бы ввести второй ref (то есть elementDisplayHeightRef), например, так:

class Calendar extends React.Component {

    /* Create a ref for the body */
    calendarBodyRef = React.createRef();

    /* Create a ref for element where height will be displayed */
    elementDisplayHeightRef = React.createRef();

    displayCurrentTimeLine = () => {

        /* Calculate body height from ref */
        const bodyHeight = this.calendarBodyRef.current.clientHeight;    

        /* Update display */
        this.elementDisplayHeightRef.current.innerText = `bodyHeight:${bodyHeight}`
    }

    render() {
        return (
            <table>
                <thead></thead>
                <tbody ref={this.calendarBodyRef}>
                    <td><td>Some row</td></td>
                    {/* Bind display ref */ }
                    <tr><td ref={this.elementDisplayHeightRef}></td></tr>
                </tbody>
            </table>
        );
    }

    /* Add did mount life cycle hook, and trigger display of body height */
    componentDidMount() {

      this.displayCurrentTimeLine()
    }
}

Этот подход вызывает displayCurrentTimeLine() во время ловушки жизненного цикла componentDidMount() (которая сама вызывается после первого render()), чтобы обеспечить полную инициализацию обоих refs, прежде чем логика компонента взаимодействует с ними в displayCurrentTimeLine().

Надеюсь, это поможет!

...