У меня есть компонент реагирования, который должен отображать интерактивную карту с маркерами, показывающими места рядом с текущим местоположением центра карты.
Я использую буклет для отображения карты, и данные о местах хранятся в 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='© <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 , но я не был уверен, как заставить это работать в моем случае, поэтому решил запросить пожарный магазин напрямую.