(1) input 갯수만큼 늘어나는 useState, event handler 들
// src/App.jsx
import React from "react";
import { useState } from "react";
const App = () => {
// input의 갯수가 늘어날때마다 state와 handler가 같이 증가한다.
const [title, setTitle] = useState("");
const onChangeTitleHandler = (e) => {
setTitle(e.target.value);
};
// input의 갯수가 늘어날때마다 state와 handler가 같이 증가한다.
const [body, setBody] = useState("");
const onChangeBodyHandler = (e) => {
setBody(e.target.value);
};
return (
<div>
<input
type="text"
name="title"
value={title}
onChange={onChangeTitleHandler}
/>
<input
type="text"
name="title"
value={body}
onChange={onChangeBodyHandler}
/>
</div>
);
};
export default App;
위의 코드는 input을 구현하고 useState로 각 input의 value를 관리하는 아주 친숙한 코드 다. 좋은 코드이지만, 조금 아쉬운 부분은 input의 개수가 증가하면 useState와 이벤트핸들러도 같이 증가하고 그로 인해 코드의 중복이 생긴다는 점이다.
지금은 input이 단지 2개이기때문에 복잡해보이지 않으나 만약 input이 수십개가 되면 중복코드가 점점 더 많이 발생한다
리액트에서는 위 예시처럼 반복되는 로직이나 중복되는 코드를 우리만의 훅, 즉 커스텀 훅을 통해서 관리할 수 있다. 리액트에서 제공하는 useState, useEffect와 같은 내장 훅을 사용해서 우리만의 훅을 만드는 것이다.
(2) 우리의 첫 custom hook → useInput
우리가 처음으로 만들 커스텀훅은 `useInput` 이라는 것 이다. input을 관리하는 훅이니까 useInput이라고 이름을 지은 것뿐이다. 커스텀 훅을 만들때 이름은 내 마음대로 해도 상관이 없으나, **단! 파일의 이름 앞에 `use` 라는 키워드를 붙여줘야 한다.**
src 폴더에 보통 hooks 라는 폴더를 생성해서 커스텀 훅들을 보관하는 식으로 많은 개발자들이 디렉토리 구조를 설계한다.
(3) 코드 구현하기
hooks 폴더에 useInput 이라는 파일을 생성하고, 아래 코드를 한줄씩 분석하면서 입력해보자.
// src/hooks/useInput.js
import React, { useState } from "react";
const useInput = () => {
// 2. value는 useState로 관리하고,
const [value, setValue] = useState("");
// 3. 핸들러 로직도 구현합니다.
const handler = (e) => {
setValue(e.target.value);
};
// 1. 이 훅은 [ ] 을 반환하는데, 첫번째는 value, 두번째는 핸들러를 반환합니다.
return [value, handler];
};
export default useInput;
생각보다 간단하다 사실 상 커스텀훅이란, 우리가 컴포넌트에서 구현해왔던 useState와 핸들러를 이렇게 뽑아서 따로 빼놓은 것 함수인 것이다. 그럼 이제 이것을 실제로 사용해보겠다
// src/App.jsx
import React from "react";
import useInput from "./hooks/useInput";
const App = () => {
// 우리가 만든 훅을 마치 원래 있던 훅인것마냥 사용해봅니다.
const [title, onChangeTitleHandler] = useInput();
const [body, onChangeBodyHandler] = useInput();
return (
<div>
<input
type="text"
name="title"
value={title}
onChange={onChangeTitleHandler}
/>
<input
type="text"
name="title"
value={body}
onChange={onChangeBodyHandler}
/>
</div>
);
};
export default App;
어떤가요? 기능은 커스텀훅을 만들기전과 동일하게 작동하되, 중복코드가 사라지고 전체적인 코드의 양도 감소했다이것이 커스텀 훅의 힘이다 앞으로 러가지 기능을 구현하면서 중복되는 로직이 있으면 “이것을 어떻게 훅으로 빼볼 수 있을까” 라고 생각해보는 습관을 가지면 좋을 것 같다
use
라는 키워드가 들어가야 한다.