input을 구현하고 useState로 각 input의 value와 onChange를 엮는 일은 아주 친숙하다. 그러나 input의 개수가 증가하면 useState와 이벤트핸들러도 같이 증가하고, 그로 인해 코드의 중복이 생긴다는 단점이 있다.
// 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;
React에서는 위 예시처럼 반복되는 로직이나 중복되는 코드를 우리만의 훅을 만들어 관리할 수 있다.
// 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;
hooks 폴더 안에 useInput이라는 파일을 생성하고 export 해보자
커스텀 훅 이란, 우리가 컴포넌트에서 구현해왔던 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;
사용할 때는 useState를 사용할 때처럼 배열을 구조분해할당하여 꺼내어 쓰면 된다.
기능은 커스텀 훅을 만들기 전과 동일하게 작동하되, 중복 코드가 사라지고, 전체적인 코드의 양도 감소한다는 장점이 있다.