Stack Overflow на русском Asked by Alexandr Antonenko on August 30, 2021
Необходимо в жизненном цикле ComponentDidMount
компонента получить размеры элемента, для этого в методе render()
я повесил ссылку на элемент:
public render() {
return (
<div ref={this.gridRef} id="grid-widget" className="h-100 overflow-hidden w-100 p-0 d-flex flex-column">
{this.renderGrid()}
</div>
);
}
В ComponentDidMount получаю элемент и беру его размеры:
public componentDidMount() {
this.props.recalculateGrid({
width: this.gridRef.current.offsetWidth,
height: this.gridRef.current.offsetHeight
});
}
Но дело в том, что в данный момент размеры элемента w = 0 и h = 0. Хотя если открыть разметку, то элемент имеет размеры.
Причем до определенного момента это работало, после изменения стилей это сломалось, к сожалению, конкретное изменение сложно найти, но хотелось бы понять, почему так вообще происходит.
Можно ли повесить на элемент какой то коллбэк, который сработает тогда, когда у элемента будут размеры?
Я решил свою проблему. Пробовал useEffect это не помогло. Пробовал использовать setTimeout, иногда помогает, иногда вываливаются ошибки связанные с рекурсией. Пробовал MutationObserver, но, к сожалению, он не реагирует на изменение размеров блока.
Мне пришлось откатывать коммиты и смотреть когда этот баг пропадет. Хочу обратить внимание, что баг воспроизводится не с первого раза, иногда нужно несколько раз перезагрузить страницу.
Компонент Grid, с которым у меня была проблема лежит в контейнере. Помимо него в этом контейнере есть еще два компонента. Все три компонента я импортировал в контейнер с помощью lazy import. Я переписал это на обычные импорты.
Сам компонент контейнера вместе с другими компонентами (достаточно простыми) так же импортировался с помощью lazy import. Импорт контейнера я оставил на lazy, а вот у компонентов, которые импортировались рядом с этим контейнером я убрал lazy импорт и это помогло.
Но таким решением я не очень доволен, оно не чувствуется надежным. Так что я продолжаю поиски более надежного метода.
Answered by Alexandr Antonenko on August 30, 2021
React никак не отвечает за отрисовку стилей. цикл componentDidMount
сработает тогда, когда у компонента будут смонтирована разметка и его логика. за отрисовку и перерисовку отвечают графические движки (например, WebKit) и сам JS движок (его EventLoop). это процесс банально называется repaint/redraw
.
в результате, теоретически, EventLoop первоначально отрисовывает Ваш компонент, ставит в очередь componentDidMount и только после этого делает redraw
Вашего документа
Answered by Август on August 30, 2021
Дело явно в стилях или в том, что соседние компоненты делают что-то асинхронно. Для того, чтобы сказать, что конкретно не так, в вопросе кода недостаточно. Обрати внимание, что хотя componentDidMount
вызывается когда текущий элемент примонтирован, может оказаться, что последующие элементы (sibling) ещё нет (у меня с ангуляром была такая проблема).
Что касается второй части вопроса - можно ли отследить изменение размеров dom-элемента: в современных браузерах имеется ResizeObserver
, который предназначен именно для этого. Но это не означает, что стоит его бросаться использовать - вполне допускаю, что есть более хорошее решение, задействующее только css.
Answered by Qwertiy on August 30, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP