api요청 보내는 컴포넌트마다 중복되는 코드가 많아서,
이를 훅으로 만들어 해결하려고 했다.
// useApi.jsx
import { useState } from 'react';
import { useCookies } from 'react-cookie';
function useApi() {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [cookie] = useCookies('accessToken');
const baseURL = "https://kangwedance.site/dev"
// [1]. method는 restful api의 메소드, requestBody는 api요청 시 필요한 데이터(객체)
async function fetchApi(method, url, requestBody) {
try {
const response = await fetch(baseURL+url, {
method: method,
headers: {
'Content-Type': 'application/json',
accesstoken: cookie.accessToken,
},
body: JSON.stringify(requestBody)
});
const json = await response.json();
console.log(json)
setData(json);
} catch (error) {
setError(error);
} finally {
setIsLoading(false);
}
}
// [2]. api요청할 컴포넌트에서) 요청이 여러개이면, data:childData 이런식으로 꺼내면 된다.
return { data, isLoading, error, fetchApi };
}
export default useApi;
// ComponentA
...
function ComponentA(props) {
const dispatch = useDispatch()
const {data, isLoading, error, fetchApi} = useApi()
useEffect(()=>{
fetchApi("GET", '/children')
},[])
useEffect(()=>{
if (data){
dispatch(getChildState(data.data))
}
}, [data])
return (
<Wrapper>
<ProfileImg/>
</Wrapper>
);
}
export default ComponentA;
response가 반환된 이후의 작업까지 fetchApi의 인자로 넘겨서 처리하도록 하면 훅을 호출한 컴포넌트에서 useEffect의 중복을 줄일 수 있을 것 같았다.
import { useState, useEffect } from 'react';
import { useCookies } from 'react-cookie';
function useApi() {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
const [cookie] = useCookies('accessToken');
const baseURL = "https://kangwedance.site/dev"
// [1]. method는 restful api의 메소드, requestBody는 api요청 시 필요한 데이터(객체)
async function fetchApi(method, url, requestBodyOrCallback, onSuccess) {
// 3번째 인자 body인지 콜백인지 확인
let requestBody;
if (typeof requestBodyOrCallback === 'function') onSuccess = requestBodyOrCallback;
else requestBody = requestBodyOrCallback;
try {
const response = await fetch(baseURL+url, {
method: method,
headers: {
'Content-Type': 'application/json',
accesstoken: cookie.accessToken,
},
body: JSON.stringify(requestBody)
});
if (!response.ok) throw new Error(`HTTP error: ${response.status}`)
const json = await response.json();
console.log(json)
setData(json);
if (onSuccess) onSuccess(json)
} catch (error) {
setError(error);
console.error(error)
} finally {
setIsLoading(false);
}
}
// [2]. api요청할 컴포넌트에서) 요청이 여러개이면, data:childData 이런식으로 꺼내면 된다.
return { data, isLoading, error, fetchApi };
}
export default useApi;
// ComponentA
...
function ComponentA(props) {
const dispatch = useDispatch()
const {data, isLoading, error, fetchApi} = useApi()
useEffect(()=>{
fetchApi("GET", '/children', onGetChildStateSuccess)
},[])
// fetchApi의 3번쨰 인자로 콜백함수를 넘겨서,
//res가 성공적으로 반환된 이후의 작업을 처리한다.
const onGetChildStateSuccess = (json)=>{
dispatch(getChildState(json.data))
}
return (
<Wrapper>
<ProfileImg/>
</Wrapper>
);
}
export default ComponentA;