[React] React 비동기 데이터 처리 최적화: 로딩, 에러, 재시도 로직
React Query와 같은 라이브러리를 사용하면 데이터 패칭, 캐싱, 동기화 및 에러 처리를 훨씬 더 쉽게 관리할 수 있으니 추후 공부하도록 하자!
1. 로딩 상태와 에러 처리
로딩 상태와 에러 상태를 별도의 state로 관리하여 더 명확하게 로딩 중 메시지와 에러 메시지를 표시할 수 있다.
import { useEffect, useState } from "react";
import axios from "axios";
const MainPage = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true); // 처음에 들어오면 로딩 활성화
const [error, setError] = useState(null); /// 에러를 저장
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
setData(response.data);
} catch (error) {
setError(error);
} finally {
setLoading(false); // 데이터 요청 완료 후 로딩 상태 업데이트
}
};
fetchData();
}, []);
if (loading) {
return <div>로딩중...</div>;
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div>
{data.length > 0 ? (
<>
{data.map((data) => (
<div key={data.id}>{data.title}</div>
))}
</>
) : (
<div>No Data Available</div>
)}
</div>
);
};
export default MainPage;
2. 로딩 스피너 사용하기
로딩 중 메시지 대신 react-spinners와 같은 라이브러리를 사용하여 쉽게 로딩 스피너를 추가할 수 있다.
먼저, react-spinners 라이브러리를 설치하자
yarn add react-spinners
그런 다음, 로딩 스피너를 사용하여 로딩 중 상태를 표시하자.
import { useEffect, useState } from "react";
import { ClipLoader } from "react-spinners";
import axios from "axios";
const MainPage = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/posts"
);
if (!response || !response.data) {
throw new Error("Data not found");
}
setData(response.data);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
if (loading) {
return (
<div className="loading-container">
<ClipLoader size={150} />
</div>
);
}
if (error) {
return <div>Error: {error.message}</div>;
}
return (
<div className="main-container">
{data.length > 0 ? (
data.map((item) => (
<div key={item.id} className="item">
{item.title}
</div>
))
) : (
<div>No Data Available</div>
)}
</div>
);
};
export default MainPage;
3. 재시도 버튼 추가하기
네트워크 요청이 실패했을 때 사용자가 요청을 다시 시도할 수 있도록 재시도 버튼을 추가할 수 있다.
import React, { useEffect, useState } from "react";
const MainPage = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const fetchData = async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(
"https://jsonplaceholder.typicode.com/posts"
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
setData(data);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchData();
}, []);
if (loading) {
return <div>로딩중,..</div>;
}
if (error) {
return (
<div>
Error: {error.message}
<button onClick={fetchData}>재시도</button>
</div>
);
}
return (
<div>
{data.length > 0 ? (
<>
{data.map((item) => (
<div key={item.id}>{item.title}</div>
))}
</>
) : (
<div>No Data Available</div>
)}
</div>
);
};
export default MainPage;
댓글남기기