#reactjs #axios #fetching-strategy
#reactjs #axios #стратегия выборки
Вопрос:
Мы написали пользовательский хук выборки данных, useInternalApi
который похож на useDataApi
хук в самом низу этого довольно приличного руководства по выборке данных с помощью реактивных хуков. Наше приложение извлекает много спортивных данных, и, в частности, мы пытаемся определить правильный шаблон выборки данных для нашего варианта использования, который довольно прост:
- Выборка общей информации для конкретного объекта (например, конференции NCAA)
- Используйте информацию, возвращаемую с этим объектом (массив идентификаторов команд для команд в конкретной конференции), и извлекайте информацию о каждой команде в массиве.
Для этого наш код будет выглядеть примерно так:
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 amp;amp; conferenceInfo.teamsArray) {
const [teamInfos, isLoading2, isError2] = useInternalApi('teamInfo', { teamIds: conferenceInfo.teamIds })
}
}
В приведенном выше примере conferenceId
является целым числом, teamIds
является массивом целых чисел, а комбинация 2 параметров useInternalApi
функции создает уникальный URL конечной точки для извлечения данных. Двумя основными проблемами, связанными с этим в настоящее время, являются:
- Наш
useInternalApi
перехват вызывается вif
инструкции, что запрещено правилом # 1 для перехватов. useInternalApi
в настоящее время создан для выполнения только одной выборки до определенной конечной точки. В настоящее время он не может обрабатывать массив идентификаторов команд, как указано выше.
Каков правильный шаблон выборки данных для этого? В идеале teamInfos
это был бы объект, в котором каждый ключ является teamId
для одной из команд конференции. В частности, лучше ли:
- Создайте новый внутренний хук, который может обрабатывать массив идентификаторов команд, выполнит 10-20 выборок (или столько, сколько необходимо в зависимости от длины
teamsArray
) и будет использовать Promise.all() для возврата результатов в целом. - Оставьте
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];
};
Комментарии:
1. Отменить оператор if и и прервать перехват на основе
conferenceInfo amp;amp; conferenceInfo.teamsArray
условия — поместить оператор return в первую строку перехвата, если условие не выполняется. Или, скорее, не вызывайте api 10-20 раз, что бы вы ни делали
Ответ №1:
На мой взгляд, если вам нужно использовать перехват условно, вы должны использовать этот перехват внутри отдельного компонента, а затем условно отобразить этот компонент.
Насколько я понимаю, поправьте меня, если я ошибаюсь, первоначальный вызов API возвращает массив идентификаторов, и вам нужно получить данные для каждой команды на основе этого идентификатора?
Вот как я бы сделал что-то в этом роде.
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>
)
}
Комментарии:
1. Это кажется великолепным! Просто для подтверждения, это не считается «хакерским способом обойти вызов перехватов в состоянии»? На первый взгляд не кажется, что в таком подходе есть что-то неправильное.
2. Насколько мне известно, нет. Нет ничего плохого в условном рендеринге компонентов.