Рендеринг более 1000 маркеров в React-Leaflet занимает много времени, а пользовательский опыт ужасен, мне нужно улучшить мой подход

У меня есть массив от 1000 мин до 5000 макс точек для рисования на моей карте листовок. Итак, моя функция рендеринга в компоненте карты выглядит примерно так:

renderMarkers = () => {
    return markers.map(
        (marker) => {
            return <Marker key={`${marker.id}`} position={[marker.lt, marker.lg]} ></Marker>
        }
    )
}

render() {
    <Map>
        {this.renderMarkers()}
    </Map>
}

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

Есть ли способ разделить рендеринг всех маркеров на разделы или позволить окну загружать этот javascript async или отображать значок загрузки во время работы функции карты?

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

заранее спасибо

РЕДАКТИРОВАТЬ: не нужно ничего делать с кластеризацией, поскольку он уже кластеризует маркеры, имеет отношение к тому, чтобы каким-то образом показать пользователю, что javascript запущен, поэтому ему нужно подождать, или отобразить асинхронно, чтобы карта текла.


person Jorge Rodríguez González    schedule 22.05.2018    source источник
comment
Кластеризация маркеров должна помочь уменьшить количество отображаемых маркеров.   -  person Alex Parij    schedule 22.05.2018
comment
Не решит вашу проблему сразу, но ваш key должен однозначно идентифицировать объект, поэтому отличный способ разрушить различие виртуальных доменов состоит в том, чтобы вместо этого основывать его на некоторой позиции массива. Не используйте marker-${key}, используйте какое-нибудь свойство из маркера, чтобы React не тратил время на восстановление маркеров только потому, что они поменяли местами индекс в вашем массиве.   -  person Mike 'Pomax' Kamermans    schedule 22.05.2018
comment
Хорошо, попробую завтра и сообщу о результате. Все маркеры уже сгруппированы, но разница невелика, поскольку проблема заключается в карте массива на 1000+ элементов, а не в отображении html, полученного в результате функции   -  person Jorge Rodríguez González    schedule 23.05.2018
comment
Идентификатор добавлен другим способом, все равно загружается немного медленно.   -  person Jorge Rodríguez González    schedule 23.05.2018


Ответы (1)


Ах, ошибка предположения, что реактивная парадигма лучше, но забвения, что ваши вызовы функций происходят при каждом render() вызове.

Как показывает практика, если одна и та же операция каждый раз возвращает одно и то же значение, и ваш код выполняет эту операцию много раз, вам следует кэшировать результат (или, по крайней мере, подумать о кешировании результата).

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

class Foo extends React.Component {

    getDerivedStateFromProps(nextProps, prevState) {
        if ( /* marker data has changed or */ !this._markerComponents) {
            this._markerComponents = markers.map( (marker, key) => 
                ( <Marker key={`marker-${key}`} position={[marker.lt, marker.lg]} ></Marker> )
            );
        }
    }

    render() {
        return ( <Map>{this._markerComponents}</Map> );
    }
}
person IvanSanchez    schedule 23.05.2018
comment
Спасибо за Ваш ответ. Чтобы использовать его, мне нужно было обновить, чтобы отреагировать на 16.3.2 и объявить функцию как статическую. Ваше решение уже было введено, если необходимо, в shouldComponentUpdate, но это не моя проблема, поскольку, когда пользователь перемещает карту, список меняется. Моя проблема заключается в том, чтобы показать какой-то загружаемый div во время работы javascript или асинхронно отображать html маркеров. Изменить: также объявить конструктор - person Jorge Rodríguez González; 23.05.2018
comment
Нет, я думаю, что лучше всего поместить весь набор маркеров в Leaflet, пусть Leaflet управляет их видимостью. Если вы выполняете что-то вроде динамической загрузки из сети в зависимости от состояния карты, я должен попросить вас указать это в своем вопросе. - person IvanSanchez; 23.05.2018