저번주에 솔로 프로젝트를 하면서 useEffect
메소드나 redux
로 관리하는 상태값을 변경하는 로직을 따로 빼주고 싶었다. 그런데 함수로 빼니까 오류가 나더라.. 그리고 이번에 Custom Hook을 이용하면 state 변경 메소드나 useEffect 메소드를 따로 빼주는게 가능하다는 것을 알게 되었다.
Hook은 React 16.8 버전부터 새로 추가된 React 요소이다. Hook을 사용하면 function 기반 코드(이 반대는 class 기반 코드이다)에서 상태 값과 여러 React의 기능들을 활용할 수 있다. 대표적인 내장 Hook으로는 useState
, useEffect
, useMemo
,useCallback
등이 있다.
원하는 Hook을 만들어서 반복되는 상태 변경 작업을 함수로 빼내서 작성할 수 있다. 이것이 Custom Hook이다.
import "./styles.css";
import { useEffect, useState } from "react";
export default function App() {
const [data, setData] = useState();
useEffect(() => {
fetch("data.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json"
}
})
.then((response) => {
return response.json();
})
.then((myJson) => {
setData(myJson);
})
.catch((error) => {
console.log(error);
});
}, []);
return (
<div className="App">
<h1>To do List</h1>
<div className="todo-list">
{data &&
data.todo.map((el) => {
return <li key={el.id}>{el.todo}</li>;
})}
</div>
</div>
);
}
위의 코드는 전형적인 API를 실행하는 컴포넌트 로직이다. 위의 코드를 Custom Hook으로 빼내보자.
return state?state:null
이런거 안된다는 거다. const useFetch = (fetchUrl) => {
//여기에 코드를 작성할 것임
};
export default hooks;
우선 utils/ hooks.js에 useFetch 메소드를 작성해야 한다.
기존 코드의 data state는 이 useFetch
훅에서 선언할 것이다.
const [data, setData] = useState();
<- 이렇게.
이제 fetch를 해주면
import { useEffect, useState } from "react";
const useFetch = (fetchUrl) => {
const [data, setData] = useState();
useEffect(() => {
fetch("data.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json"
}
})
.then((response) => {
return response.json();
})
.then((myJson) => {
setData(myJson);
})
.catch((error) => {
console.log(error);
});
}, []);
return data;
};
export default useFetch;
fetch한 결과를 setData로 저장하고, data를 return했다.
이제 App.js로 돌아와서 기존 코드를 수정한다.
data state의 결과값은 useFetch(url)을 실행하여 전달받을 수 있다.
import "./styles.css";
import { useEffect, useState } from "react";
import useFetch from "./util/useFetch";
export default function App() {
const data = useFetch("data.json");
return (
<div className="App">
<h1>To do List</h1>
<div className="todo-list">
{data &&
data.todo.map((el) => {
return <li key={el.id}>{el.todo}</li>;
})}
</div>
</div>
);
}