Я пытаюсь показать счетчик загрузки при извлечении данных из API и показать ошибку или результаты после завершения использования useEffect. По какой-то причине isLoading
устанавливается в false до завершения выборки.
Не могли бы вы помочь мне, в чем может быть проблема?
const ProblemTable: React.FC<IProblemTableProps> = (props) => {
// List of problems to show on the table
const [problems, setProblems] = useState<IProblem[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<Error>();
useEffect(() => {
TierService.getProblems(props.tier, setProblems, setError);
}, []);
useEffect(() => {
setIsLoading(false);
}, [problems, error]);
if (isLoading) {
return <Loading message = "Loading problems..." />;
}
if (error) {
return <ErrorMessage title = "Failed fetching problems" />;
}
return <>...</>;
useEffect
, который устанавливает загрузку в false
, вызывается при монтировании компонента. Добавьте условие, которое превращало бы загрузку в false
только после завершения вызова API.
Например, если есть какие-либо проблемы или ошибка, установите загрузку в false
:
useEffect(() => {
if (problems.length || error) setIsLoading(false);
}, [problems, error]);
Однако, если нет проблем или ошибок, loading
останется true
, поэтому вам, вероятно, понадобится более строгое условие. Лучшим способом было бы установить загрузку на false
, если какой-либо из обратных вызовов вызывается:
useEffect(() => {
TierService.getProblems(
props.tier,
p => {
setProblems(p);
setLoading(false);
}
e => {
setError(e);
setLoading(false);
}
);
}, []);
В зависимости от реализации TierService.getProblems
второе предложение потерпит неудачу, если обратный вызов не будет вызван, когда ответ пуст.
Я бы, вероятно, создал API на основе Promise, который позволил бы вам использовать async/await
с try/catch/finally
:
useEffect(() => {
const api = async () => {
try {
const problems = await TierService.getProblems(props.tier);
setProblems(problems);
} catch (e) {
setError(e);
} finally {
setLoading(false);
}
};
api();
}, []);
Результатом пустого массива была моя проблема и с вашим первым вариантом. Однако проблема решается установкой isLoading в false при объявлении, а затем в true после вызова службы. И тогда я могу очистить useEffect, вызванный изменениями в проблеме и/или ошибке. Я не знал, что этот useEffect вызывается также при монтировании компонента.