Как я могу вызвать хуки API по одному? - PullRequest
0 голосов
/ 28 февраля 2020

Я совершенно новичок в React и пытаюсь понять это, при этом сохраняя его как можно более простым.

У меня есть функциональный компонент-оболочка RestaurantMapWrapper, который должен:

  1. Получить данные геолокации из ловушки с именем usePosition.
  2. передать данные долготы и широты в ловушку с именем useYelpHook, которая извлекает данные о ресторанах, используя переданные данные широты и долготы.
  3. Визуализация данных визга (автоматически, без ввода данных пользователем).

Проблема в том, что 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 };
};

1 Ответ

0 голосов
/ 28 февраля 2020

useYelpHook useEffect запускается каждый раз, когда компонент выполняет рендеринг, и запускается зависимостями. Вы должны передать lo c непосредственно в useYelpHook useEffect вместо сохранения исходного состояния.

export function RestaurantMapWrapper(props) {
    const { latitude, longitude, timestamp, accuracy, error, isLoadingMap } = usePosition();
    const pos = useMemo(() => ({ lat: latitude, lng: longitude }), [latitude, longitude]); //ends up being undefined since neither have been retrieved yet
    const [{ data, isLoading }] = useYelpHook(pos);

    return <div>JSON.stringify({data})</div>;
const API_KEY = 'my api key';
const config = {
    headers: { Authorization: `Bearer ${API_KEY}` },
    params: {
        term: 'food',
        latitude: '0',
        longitude: '0',
        radius: '',
        sort_by: 'rating'
    }
}
export const useYelpHook = (loc) => {


    const [data, setData] = useState({ businesses: [] });
    //const [loc, setLoc] = useState(initialLoc);
    const [isLoading, setIsLoading] = useState(true);
 useEffect(() => {
        /* return if loc is invalid */
        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 }];
}

Обратите внимание на useMemo и удаление initialLo c

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...