-
Notifications
You must be signed in to change notification settings - Fork 2
Custom Hooks
Junho Lee edited this page Nov 29, 2019
·
1 revision
- 일단 훅은 이렇게 생겼다.
-
useGetFeed
는<T>
라는 제네릭 타입을 갖는다고 명시해 뒀다. 서버에서 주는 데이터의 형식이 그때그때 다르기 때문. - 리턴값은 총 5개
-
data
는 말그대로 데이터 -
setData
는 데이터를 변경하는 함수 -
isLoading
은 boolean 변수고 현재 데이터를 가져오고 있으면true
값을 갖는다. -
isError
는 데이터를 가져오는 과정에서 에러가 발생하는 경우true
가 되고 에러처리를 해주면 된다. -
setUrl
은 약간 이 훅을 발동 시키는 역할이다. 커스텀 훅 내부에서useEffect
에 dependency를url
스테이트에 걸어두었기 때문.
-
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const useGetFeed = <T>(initData:T)
:[{data:T, setData:React.Dispatch<T>, isLoading:boolean, isError:boolean}, (url:string)=>void ] => {
...
return [{
data, setData, isLoading, isError,
}, setUrl];
};
export default useGetFeed;
내부는 이렇게 생겼다. 코드가 기니까 주석으로 ㄱㄱ
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const useGetFeed = <T>(initData:T)
:[{data:T, setData:React.Dispatch<T>, isLoading:boolean, isError:boolean}, (url:string)=>void ] => {
const [data, setData] = useState(initData); // 사용자가 입력한 초기데이터로 data를 세팅한다. 근데 보통 빈배열이거나 빈객체 일듯??
const [url, setUrl] = useState(''); // 여기서 setUrl로 url 값이 바뀌면 useEffect가 실행된다.
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
useEffect(() => {
const fetchData = async () => {
setIsError(false); // 에러가 없다라고 하고 시작
setIsLoading(true); // 로딩중이다라고 하고 시작
try {
const result = await axios(url); // 서버에 데이터 요청
if (!result.data.success) {
// 요청이 실패했다면 로딩을 false로 설정한다. 지금은 잘 동작하지 않는데 여기서 에러를 던지던가 해야할듯?
setIsLoading(false);
} else {
// 요청이 성공했다면 데이터를 세팅하고 로딩은 false로 해서 로딩 멈춰주고 isError는 왜저렇게 했지? 고치자
console.log(result.data);
setData(result.data.data);
setIsLoading(false);
setIsError(true);
}
} catch (e) {
setIsError(e);
}
};
fetchData();
}, [url]); // 디펜던시를 url state에 걸어서 url이 바뀔때마다 fetchData()를 실행한다.
return [{
data, setData, isLoading, isError,
}, setUrl];
};
export default useGetFeed;
사용할때는 이렇게 했다. isLoading
이 true
일때는 로딩중이라는 컴포넌트를 띄우고 false
면 로딩이 끝낫고 데이터가 왔다는 뜻이기 때문에 우리가 원하는 데이터를 렌더링 할 수 있다.
const [{
data, setData, isLoading, isError,
}, setUrl] = useGetFeed<IData | null>(null);
useEffect(() => {
setUrl(url);
}, [data]);
const WorksDetail:React.FC<WorksDetailProp> = ({
data, isLoading, isError, commentRef, changeInputHandler, addNewComment,
}) => (
isLoading || data === null
? (<div>Loading...</div>)
: (
<S.Container/>