diff --git a/src/components/atoms/ReceiptQuotes/ReceiptQuotes.jsx b/src/components/atoms/ReceiptQuotes/ReceiptQuotes.jsx
index 8ce7899..6db98da 100644
--- a/src/components/atoms/ReceiptQuotes/ReceiptQuotes.jsx
+++ b/src/components/atoms/ReceiptQuotes/ReceiptQuotes.jsx
@@ -1,5 +1,5 @@
-import { useEffect, useState } from "react";
import * as S from "./ReceiptQuotes.styles";
+import useAsync from "../../../hooks/useAsync";
/**
* ReceiptQuotes
@@ -10,18 +10,17 @@ import * as S from "./ReceiptQuotes.styles";
* @returns
*/
export function ReceiptQuotes() {
- const [quotesState, setQuotes] = useState();
+ const [state] = useAsync(getQuotes, []);
+ const { loading, data: quote, error } = state;
+ console.log(quote);
- useEffect(() => {
- const getQuotes = async () => {
- await fetch("https://api.adviceslip.com/advice")
- .then((response) => response.json())
- .then((data) => setQuotes(data.slip.advice))
- .catch((e) => console.error(e));
- };
+ return {loading || error ? "Well done!" : quote};
+}
- getQuotes();
- }, []);
+async function getQuotes() {
+ const response = await fetch("https://api.adviceslip.com/advice").then((response) =>
+ response.json(),
+ );
- return {quotesState || "Well done!"};
+ return response.slip.advice;
}
diff --git a/src/hooks/useAsync.jsx b/src/hooks/useAsync.jsx
new file mode 100644
index 0000000..e4be0c2
--- /dev/null
+++ b/src/hooks/useAsync.jsx
@@ -0,0 +1,54 @@
+// 참고 자료 - https://react.vlpt.us/integrate-api/03-useAsync.html
+
+import { useReducer, useEffect } from "react";
+
+function reducer(state, action) {
+ switch (action.type) {
+ case "LOADING":
+ return {
+ loading: true,
+ data: null,
+ error: null,
+ };
+ case "SUCCESS":
+ return {
+ loading: false,
+ data: action.data,
+ error: null,
+ };
+ case "ERROR":
+ return {
+ loading: false,
+ data: null,
+ error: action.error,
+ };
+ default:
+ throw new Error(`Unhandled action type: ${action.type}`);
+ }
+}
+
+function useAsync(callback, deps = []) {
+ const [state, dispatch] = useReducer(reducer, {
+ loading: false,
+ data: null,
+ error: false,
+ });
+
+ const fetchData = async () => {
+ dispatch({ type: "LOADING" });
+ try {
+ const data = await callback();
+ dispatch({ type: "SUCCESS", data });
+ } catch (e) {
+ dispatch({ type: "ERROR", error: e });
+ }
+ };
+
+ useEffect(() => {
+ fetchData();
+ }, deps);
+
+ return [state, fetchData];
+}
+
+export default useAsync;