reactjs - 如何一次调用一个 API 挂钩?
问题描述
我对 React 完全陌生,并试图弄清楚这一点,同时仍使其尽可能简单。
我有一个名为的包装器功能组件RestaurantMapWrapper
,它应该:
- 从名为
usePosition
. - 将经度和纬度数据传递到一个名为 的钩子
useYelpHook
中,该钩子使用传入的纬度和经度数据检索餐馆数据。 - 渲染 yelp 数据(自动,无需用户输入)。
问题是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 };
};
解决方案
useEffect
每次组件呈现并由依赖项触发时,useYelpHook都会运行。您应该将 loc 直接传递到,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 和 initialLoc 的删除
推荐阅读
- android - Flutter 如何为 App 中各处的 MaterialButton 小部件定义单一样式?
- python - 我如何在python中对一个简单的字符串列表进行分组
- android - Android 9.0 - 如何查找用户是否插入了损坏的 SD 卡?
- python - 为什么这行代码没有返回,即使该行中有返回
- python - 我如何用一个正在克隆的盒子做一个正确的列表?
- c# - 如何通过 windows 命令创建文件链接并在该链接的目录中定义开始?
- r - 在 Shiny App 的右侧嵌入图像徽标
- rust - 我怎么知道堆栈和堆上是否有东西?
- android - android.permission.ACTIVITY_RECOGNITION 和谷歌有什么区别?
- python - 从字母表中枚举长度为 K 的字符串