在 React 中,根据初始获取的结果获取数据
In React, fetch data conditional on results of an initial fetch
我们编写了一个自定义数据获取挂钩 useInternalApi
,它类似于此 fairly decent tutorial 最底部的 useDataApi
挂钩,用于使用 React 挂钩获取数据。我们的应用程序获取大量体育数据,特别是,我们正在尝试为我们的用例找出正确的 data-fetching 模式,这非常简单:
- 获取特定实体(例如 NCAA 会议)的一般信息
- 使用该实体的信息 return(特定会议中团队的团队 ID 数组),并获取数组中每个团队的信息。
为此,我们的代码将如下所示:
import `useInternalApi` from '../path-to-hooks/useInternalApi';
// import React... and other stuff
function ComponentThatWantsTeamInfo({ conferenceId }) {
// use data fetching hook
const [conferenceInfo, isLoading1, isError1] = useInternalApi('conferenceInfo', { conferenceId: conferenceId })
// once conferenceInfo loads, then load info from all teams in the conference
if (conferenceInfo && conferenceInfo.teamsArray) {
const [teamInfos, isLoading2, isError2] = useInternalApi('teamInfo', { teamIds: conferenceInfo.teamIds })
}
}
在上面的示例中,conferenceId
是一个整数,teamIds
是一个整数数组,useInternalApi
函数的 2 个参数的组合创建了一个唯一的端点 url 从中获取数据。当前的两个主要问题是:
- 我们的
useInternalApi
挂钩在 if
语句中调用,根据挂钩的 #1 规则不允许这样做。
useInternalApi
目前构建为仅对特定端点进行一次提取。目前,它不能像上面那样处理一组 teamIds。
正确的 data-fetching 模式是什么?理想情况下,teamInfos
将是一个 object,其中每个键都是会议中一个团队的 teamId
。特别是,是否更好:
- 创建一个可以处理 teamId 数组的新内部挂钩,将进行 10 - 20 次提取(或根据
teamsArray
的长度根据需要进行提取),并将使用 Promise.all() 到 return 结果 all-together.
- 保持
useInternalApi
钩子不变,只需调用它 10 - 20 次,每个团队调用一次。
编辑
我不确定是否需要 useInternalApi
的基础代码来回答这个问题。我尽量避免创建很长的帖子,但在这种情况下,代码可能很重要:
const useInternalApi = (endpoint, config) => {
// Set Data-Fetching State
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState(false);
// Use in lieu of useEffect
useDeepCompareEffect(() => {
// Token/Source should be created before "fetchData"
let source = axios.CancelToken.source();
let isMounted = true;
// Create Function that makes Axios requests
const fetchData = async () => {
// Set States + Try To Fetch
setIsError(false);
setIsLoading(true);
try {
const url = createUrl(endpoint, config);
const result = await axios.get(url, { cancelToken: source.token });
if (isMounted) {
setData(result.data);
}
} catch (error) {
if (isMounted) {
setIsError(true);
}
} finally {
if (isMounted) {
setIsLoading(false);
}
}
};
// Call Function
fetchData();
// Cancel Request / Prevent State Updates (Memory Leaks) in cleanup function
return () => {
isMounted = false; // set to false to prevent state updates / memory leaks
source.cancel(); // and cancel the http request as well because why not
};
}, [endpoint, config]);
// Return as length-3 array
return [data, isLoading, isError];
};
在我看来,如果你需要有条件地使用一个钩子,你应该在一个单独的组件中使用那个钩子,然后有条件地渲染那个组件。
我的理解,如果我错了请纠正我,最初的 API 调用 returns 一个 ID 数组,您需要根据该 ID 为每个团队获取数据吗?
下面是我会如何做这类事情。
import `useInternalApi` from '../path-to-hooks/useInternalApi';
// import React... and other stuff
function ComponentThatDisplaysASpecificTeam(props){
const teamId = props.teamId;
const [teamInfo] = useInternalApi('teamInfo', { teamId });
if(! teamInfo){
return <p>Loading...</p>
}
return <p>do something with teamInfo...</p>
}
function ComponentThatWantsTeamInfo({ conferenceId }) {
// use data fetching hook
const [conferenceInfo, isLoading1, isError1] = useInternalApi('conferenceInfo', { conferenceId: conferenceId })
if (! conferenceInfo || ! conferenceInfo.teamsArray) {
return <p>this is either a loading or an error, you probably know better than me.</p>
}
// Let the data for each team be handled by its own component. This also lets you not have to use Promise.all
return (
<div>
{conferenceInfo.teamIds.map(teamId => (
<ComponentThatDisplaysASpecificTeam teamId={teamId} />
))}
</div>
)
}
我们编写了一个自定义数据获取挂钩 useInternalApi
,它类似于此 fairly decent tutorial 最底部的 useDataApi
挂钩,用于使用 React 挂钩获取数据。我们的应用程序获取大量体育数据,特别是,我们正在尝试为我们的用例找出正确的 data-fetching 模式,这非常简单:
- 获取特定实体(例如 NCAA 会议)的一般信息
- 使用该实体的信息 return(特定会议中团队的团队 ID 数组),并获取数组中每个团队的信息。
为此,我们的代码将如下所示:
import `useInternalApi` from '../path-to-hooks/useInternalApi';
// import React... and other stuff
function ComponentThatWantsTeamInfo({ conferenceId }) {
// use data fetching hook
const [conferenceInfo, isLoading1, isError1] = useInternalApi('conferenceInfo', { conferenceId: conferenceId })
// once conferenceInfo loads, then load info from all teams in the conference
if (conferenceInfo && conferenceInfo.teamsArray) {
const [teamInfos, isLoading2, isError2] = useInternalApi('teamInfo', { teamIds: conferenceInfo.teamIds })
}
}
在上面的示例中,conferenceId
是一个整数,teamIds
是一个整数数组,useInternalApi
函数的 2 个参数的组合创建了一个唯一的端点 url 从中获取数据。当前的两个主要问题是:
- 我们的
useInternalApi
挂钩在if
语句中调用,根据挂钩的 #1 规则不允许这样做。 useInternalApi
目前构建为仅对特定端点进行一次提取。目前,它不能像上面那样处理一组 teamIds。
正确的 data-fetching 模式是什么?理想情况下,teamInfos
将是一个 object,其中每个键都是会议中一个团队的 teamId
。特别是,是否更好:
- 创建一个可以处理 teamId 数组的新内部挂钩,将进行 10 - 20 次提取(或根据
teamsArray
的长度根据需要进行提取),并将使用 Promise.all() 到 return 结果 all-together. - 保持
useInternalApi
钩子不变,只需调用它 10 - 20 次,每个团队调用一次。
编辑
我不确定是否需要 useInternalApi
的基础代码来回答这个问题。我尽量避免创建很长的帖子,但在这种情况下,代码可能很重要:
const useInternalApi = (endpoint, config) => {
// Set Data-Fetching State
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState(false);
// Use in lieu of useEffect
useDeepCompareEffect(() => {
// Token/Source should be created before "fetchData"
let source = axios.CancelToken.source();
let isMounted = true;
// Create Function that makes Axios requests
const fetchData = async () => {
// Set States + Try To Fetch
setIsError(false);
setIsLoading(true);
try {
const url = createUrl(endpoint, config);
const result = await axios.get(url, { cancelToken: source.token });
if (isMounted) {
setData(result.data);
}
} catch (error) {
if (isMounted) {
setIsError(true);
}
} finally {
if (isMounted) {
setIsLoading(false);
}
}
};
// Call Function
fetchData();
// Cancel Request / Prevent State Updates (Memory Leaks) in cleanup function
return () => {
isMounted = false; // set to false to prevent state updates / memory leaks
source.cancel(); // and cancel the http request as well because why not
};
}, [endpoint, config]);
// Return as length-3 array
return [data, isLoading, isError];
};
在我看来,如果你需要有条件地使用一个钩子,你应该在一个单独的组件中使用那个钩子,然后有条件地渲染那个组件。
我的理解,如果我错了请纠正我,最初的 API 调用 returns 一个 ID 数组,您需要根据该 ID 为每个团队获取数据吗?
下面是我会如何做这类事情。
import `useInternalApi` from '../path-to-hooks/useInternalApi';
// import React... and other stuff
function ComponentThatDisplaysASpecificTeam(props){
const teamId = props.teamId;
const [teamInfo] = useInternalApi('teamInfo', { teamId });
if(! teamInfo){
return <p>Loading...</p>
}
return <p>do something with teamInfo...</p>
}
function ComponentThatWantsTeamInfo({ conferenceId }) {
// use data fetching hook
const [conferenceInfo, isLoading1, isError1] = useInternalApi('conferenceInfo', { conferenceId: conferenceId })
if (! conferenceInfo || ! conferenceInfo.teamsArray) {
return <p>this is either a loading or an error, you probably know better than me.</p>
}
// Let the data for each team be handled by its own component. This also lets you not have to use Promise.all
return (
<div>
{conferenceInfo.teamIds.map(teamId => (
<ComponentThatDisplaysASpecificTeam teamId={teamId} />
))}
</div>
)
}