我正在编写一个reactjs网络应用程序,在这里我首先需要加载一个度假村列表,然后,在用户选择其中一个之后,加载度假村的所有细节。
这是我的useFetch函数:
const useFetch = (url, options) => {
const [response, setResponse] = React.useState(null);
const [error, setError] = React.useState(null);
const [isLoading, setIsLoading] = React.useState(false);
React.useEffect(() => {
(async () => {
setIsLoading(true);
try {
const res = await fetch(url, options);
const json = await res.json();
setResponse(json);
setIsLoading(false);
} catch (error) {
setError(error);
setIsLoading(false);
}
})();
}, []);
return [ response, error, isLoading ];
};在我的组件中,我使用它检索度假村列表,没有任何问题:
function App() {
const [resorts, resortsIsLoading, resortsError] = useFetch(config.API_URL_GET_RESORTS);
const [resortId, setResortId] = useState(null);
const handleChangeResort = (event) => {
const id = event.target.value;
setResortId(id);
};
return (
<>
<Select
labelId="resort-label"
id="resort"
label="resort"
value={resort ? resort.id : ""}
onChange={handleChangeResort}
>
{resorts.length ? (
resorts.map(c => (
<MenuItem key={c.id} value={c.id}>
{c.name}
</MenuItem>
))
) : (
<MenuItem key={0} value={""}>
<em>loading resorts list...</em>
</MenuItem>
)}
</Select>
</>
)}
}问题是,在第一个useFetch调用之后,我无法添加一个useFetch来获取所选的度假胜地详细信息:
const [resorts, resortsIsLoading, resortsError] = useFetch(config.API_URL_GET_RESORTS);
const [resort, resortIsLoading, resortError] = useFetch(config.API_URL_GET_RESORT, {id: resortId});因为最初我还没有resortId。
我需要这样的东西:
useEffect(() => {
if (resortId !== null) {
const [resort, resortIsLoading, resortError] = useFetch(config.API_URL_GET_RESORT, {id: resortId});
}
}, [resortId]);但是useEffect()内部不能用钩子.
我应该采用什么解决方案来使用useFetch()逻辑(我非常喜欢它,因为它隐藏了从邮件应用程序逻辑中获取的细节)的条件方式(即:在resortId可用之后)?
发布于 2020-10-21 08:55:41
钩子可以提供一个函数来获取/重新获取数据:
const useFetch = (url, options) => {
const [response, setResponse] = React.useState(null);
const [error, setError] = React.useState(null);
const [isLoading, setIsLoading] = React.useState(false);
const fetchData = async (resortId) => {
setIsLoading(true);
try {
const res = await fetch(url, {id: resortId});
const json = await res.json();
setResponse(json);
setIsLoading(false);
} catch (error) {
setError(error);
setIsLoading(false);
}
}
return [
response,
error,
isLoading,
fetchData
];
};然后,只要您想更新搜索,就可以调用fetchData:
const App = () => {
const [resort, resortIsLoading, resortError, fetchResort] = useFetch(config.API_URL_GET_RESORT);
const handleChangeResort = (event) => {
const id = event.target.value;
fetchResort(id);
};
return (
<>
<Select
labelId="resort-label"
id="resort"
label="resort"
value={resort ? resort.id : ""}
onChange={handleChangeResort}
>
{resorts.length ? (
resorts.map(c => (
<MenuItem key={c.id} value={c.id}>
{c.name}
</MenuItem>
))
) : (
<MenuItem key={0} value={""}>
<em>loading resorts list...</em>
</MenuItem>
)}
</Select>
</>
)}
}发布于 2020-10-21 09:13:09
我会这样做:
const useFetch = (url) => {
const [state, setState] = React.useState([null, false, null]);
const fetchData = async (options) => {
setState([null, true, null]);
try {
const res = await fetch(url, options);
const json = await res.json();
setState([json, false, null]);
} catch (error) {
setState([null, false, error]);
}
}
return [
...state, // response, loading, error
fetchData
];
};然后,你可以用:
const [resorts, resortsIsLoading, resortsError, fetchResorts] = useFetch(config.API_URL_GET_RESORTS);
const [resort, resortIsLoading, resortError, fetchResort] = useFetch(config.API_URL_GET_RESORT);
useEffect(() => {
fetchResorts()
}, [])https://stackoverflow.com/questions/64459774
复制相似问题