В React выборка данных зависит от результатов начальной выборки

#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 конечной точки для извлечения данных. Двумя основными проблемами, связанными с этим в настоящее время, являются:

  1. Наш useInternalApi перехват вызывается в if инструкции, что запрещено правилом # 1 для перехватов.
  2. useInternalApi в настоящее время создан для выполнения только одной выборки до определенной конечной точки. В настоящее время он не может обрабатывать массив идентификаторов команд, как указано выше.

Каков правильный шаблон выборки данных для этого? В идеале teamInfos это был бы объект, в котором каждый ключ является teamId для одной из команд конференции. В частности, лучше ли:

  1. Создайте новый внутренний хук, который может обрабатывать массив идентификаторов команд, выполнит 10-20 выборок (или столько, сколько необходимо в зависимости от длины teamsArray ) и будет использовать Promise.all() для возврата результатов в целом.
  2. Оставьте 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. Насколько мне известно, нет. Нет ничего плохого в условном рендеринге компонентов.