Как избежать обращения к пожарному хранилищу в неопределенном l oop при использовании гео-запросов, основанных на текущей позиции на листовой карте? - PullRequest
0 голосов
/ 18 января 2020

У меня есть компонент реагирования, который должен отображать интерактивную карту с маркерами, показывающими места рядом с текущим местоположением центра карты.

Я использую буклет для отображения карты, и данные о местах хранятся в Cloud Firestore в коллекции «мест». Поскольку я не хочу получать каждый документ из этой коллекции сразу, я хочу запросить в пожарном хранилище только те места, которые находятся, например, в радиусе 1000 км от центра текущей карты. Что касается самого запроса, я следую подходу, представленному в этом видео. Я запускаю запрос firestore каждый раз, когда карта перемещается / изменяется.

Теперь моя проблема в том, что после в первый раз, когда я делаю движение на карте, триггер moveEnd вызывается на неопределенный срок в al oop, снова и снова запрашивая firestore, что, конечно, не то, что я хочу. Это происходит только тогда, когда на самом деле есть результат в моем запросе.

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

Это код, который я использую для своего компонента:

import React, { useState } from 'react';
import { Container } from '@material-ui/core';
import { Map, TileLayer, Marker, Popup, LatLngBounds } from 'react-leaflet';
import { LatLngLiteral, LeafletEvent } from 'leaflet';
import ReactLeafletSearch from 'react-leaflet-search';
import { PlaceData } from '../types';
import { useFirestore } from 'react-redux-firebase';
import { geohashQueries } from '../utils/geofire';

interface State {
  zoom: number;
  center: LatLngLiteral;
  bounds: LatLngBounds | undefined;
  places: PlaceData[];
}

const MyMap = () => {
  const [state, setState] = useState<State>({
    zoom: 13,
    center: { lat: 51.505, lng: -0.09 },
    bounds: undefined,
    places: [],
  });

  const firestore = useFirestore();
  const collection = firestore.collection('places');

  const handleLoad = (event: LeafletEvent) => {
    console.log('handleLoad()');
  };

  const handleMoveend = (event: LeafletEvent) => {
    console.log('handleMoveend()');

    const center = event.target.getCenter();
    setState({ ...state, center, bounds: event.target.getBounds() });

    const radiusInKm = 1000;
    const geohashesToQuery = geohashQueries([center.lat, center.lng], radiusInKm);

    const whereQueries = geohashesToQuery.map(range => {
      return collection.where('geohash', '>=', range[0]).where('geohash', '<=', range[1]);
    });

    whereQueries.forEach(query => {
      query.get().then(snap => {
        snap.forEach(doc => {
          const data = doc.data() as PlaceData;
          let places = state.places;
          places.push(data);
          setState({ ...state, places });
        });
      });
    });
  };

  return (
    <Container>
      <Map center={state.center} zoom={state.zoom} onLoad={handleLoad} onMoveend={handleMoveend}>
        <TileLayer
          attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
        />
        {state.places.map((data, idx) => (
          <Marker key={`place-${idx}`} position={[data.geopoint.latitude, data.geopoint.longitude]}>
            <Popup>
              <span>{data.title}</span>
            </Popup>
          </Marker>
        ))}
        <ReactLeafletSearch position="topleft" zoom={state.zoom} />
      </Map>
    </Container>
  );
};

export default MyMap;

Если у кого-то есть указатель для меня, это будет очень признательно! Да, и еще, я довольно новичок с точки зрения пожарного магазина, реактивных зацепок и редуксов, так что если есть что-то еще, что я должен сделать лучше или иначе, пожалуйста, дайте мне знать. Например, в другом месте моего приложения я использовал firestoreConnect из используемой мной библиотеки actate-redux-firebase , но я не был уверен, как заставить это работать в моем случае, поэтому решил запросить пожарный магазин напрямую.

...