Я совершенно новичок в React и пытаюсь понять это, при этом сохраняя его как можно более простым.
У меня есть функциональный компонент-оболочка RestaurantMapWrapper
, который должен:
- Получить данные геолокации из ловушки с именем
usePosition
. - передать данные долготы и широты в ловушку с именем
useYelpHook
, которая извлекает данные о ресторанах, используя переданные данные широты и долготы. - Визуализация данных визга (автоматически, без ввода данных пользователем).
Проблема в том, что usePosition
не получает местоположение во времени, поэтому useYelpHook
не работает с. Если для pos
установить значение по умолчанию, то useYelpHook
больше никогда не будет вызываться.
Как я могу убедиться, что useYelpHook
ждет usePosition
перед рендерингом? Это как-то связано с асинхронностью одного хука?
export function RestaurantMapWrapper(props) {
const { latitude, longitude, timestamp, accuracy, error, isLoadingMap } = usePosition();
const pos = { lat: latitude, lng: longitude }; //ends up being undefined since neither have been retreived yet
const [{ data, isLoading }, setLoc] = useYelpHook(pos); //is there somewhere I could call setLoc?
return <div>JSON.stringify({data})</div>;
export const useYelpHook = (initialLoc) => {
const API_KEY = 'my api key';
const config = {
headers: { Authorization: `Bearer ${API_KEY}` },
params: {
term: 'food',
latitude: '0',
longitude: '0',
radius: '',
sort_by: 'rating'
}
}
const [data, setData] = useState({ businesses: [] });
const [loc, setLoc] = useState(initialLoc);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
config.params.latitude = loc.lat;
config.params.longitude = loc.lng;
const fetchData = async () => {
setIsLoading(true);
const result = await axios(`${'https://cors-anywhere.herokuapp.com/'}https://api.yelp.com/v3/businesses/search`, config);
setData(result.data);
setIsLoading(false);
};
fetchData();
}, [loc])
return [{ data, isLoading }, setLoc];
}
import { useState, useEffect } from 'react';
const defaultSettings = {
enableHighAccuracy: false,
timeout: Infinity,
maximumAge: 0,
};
export const usePosition = (settings = defaultSettings) => {
const [position, setPosition] = useState({});
const [error, setError] = useState(null);
const [isLoadingMap, setIsLoadingMap] = useState(true);
const onChange = ({ coords, timestamp }) => {
setPosition({
latitude: coords.latitude,
longitude: coords.longitude,
accuracy: coords.accuracy,
timestamp,
});
};
const onError = (error) => {
setError(error.message);
};
useEffect(() => {
setIsLoadingMap(true);
const geo = navigator.geolocation;
if (!geo) {
setError('Geolocation is not supported');
return;
}
geo.getCurrentPosition(onChange, onError, settings);
setIsLoadingMap(false);
}, [settings]);
return { ...position, error, isLoadingMap };
};