리액트에서는 사용자가 직접 정의한 커스텀 훅을 만드는 것이 가능합니다. 애시당초 리액트 훅 자체가 불필요한 반복 작업을 줄이면서도 더욱 간결하게 코드를 구성하기 위해 만들어진 기능인걸요.
컴포넌트를 10개, 20개씩 만들다보면 비슷한 훅 함수가 만들어질 수 있겠죠. 이런 비슷한 훅들을 하나로 통합하도록 설정하는 것이 커스텀 훅 입니다.
// ForwardCounter.js
import { useState, useEffect } from 'react';
import Card from './Card';
const ForwardCounter = () => {
const [counter, setCounter] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCounter((prevCounter) => prevCounter + 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <Card>{counter}</Card>;
};
export default ForwardCounter;
// BackwardCounter.js
import { useState, useEffect } from 'react';
import Card from './Card';
const BackwardCounter = () => {
const [counter, setCounter] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setCounter((prevCounter) => prevCounter - 1);
}, 1000);
return () => clearInterval(interval);
}, []);
return <Card>{counter}</Card>;
};
export default BackwardCounter;
해당 js 파일 2가지는 동일한 useState()와 비슷한 useEffect() 함수를 가지고 있습니다. 이를 커스텀 훅을 통해 별도로 모듈화하여 하나로 통합시켜 봅시다. 여기서 중요한 점은, 모듈화하는 함수명은 기존의 훅들과 동일하게 use 로 시작해야합니다.
// use-counter.js
import { useState, useEffect } from "react";
const useCounter = (forwards = true) => {
const [counter, setCounter] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
if (forwards) {
setCounter((prevCounter) => prevCounter + 1);
} else {
setCounter((prevCounter) => prevCounter - 1);
}
}, 1000);
return () => clearInterval(interval);
}, [forwards]);
return counter;
};
export default useCounter;
// ForwardCounter.js
import Card from "./Card";
import useCounter from "../hooks/use-counter.js";
const ForwardCounter = () => {
const counter = useCounter();
return <Card>{counter}</Card>;
};
export default ForwardCounter;
// BackwardCounter.js
import Card from "./Card";
import useCounter from "../hooks/use-counter";
const BackwardCounter = () => {
const counter = useCounter(false);
return <Card>{counter}</Card>;
};
export default BackwardCounter;