리액트로 프로젝트를 생성하여 개발하는 과정 중 리액트의 필수 문법 및 기초적인 부분, 심화 과정 등을 정리한 문서입니다. 정리한 부분에는 제가 이해하는 관점에서만 정리를 하였기 때문에 초점은 보여주는 형식이 아닌 제가 필요할 때 사용하려는 목적이 담겨져 있습니다. 컴포넌트를 만들다보면, 반복되는 로직이 자주 발생합니다. 예를 들어서 input 을 관리하는 코드는 관리 할 때마다 꽤나 비슷한 코드가 반복되죠. 이번에는 그러한 상황에 커스텀 Hooks 를 만들어서 반복되는 로직을 쉽게 재사용하는 방법을 알아보겠습니다.
현재 정리부터는 소스코드를 제공할 예정입니다. 제공하는 소스코드를 이용하여 따라하실 수 있고 개념을 확실히 잡을 꺼 같아서 올리게 되었습니다. 소스코드 자료는 아래 링크를 참고해주세요.
https://github.com/libtv/React_Note/tree/master/16.%20customHook
그러면 custom Hook 을 만들어봅시다.
# Contents
- custom Hooks 만들기
# custom Hooks 만들기
커스텀 훅을 만드는 방법은 아주 간단합니다. 그냥, 그 안에서 useState, useEffect, useReducer, useCallback 등 Hooks 를 사용하여 원하는 기능을 구현해주고, 컴포넌트에서 사용하고 싶은 값들을 반환해주면 됩니다.
그러면 본격적으로 우리가 사용하는 예제를 통해 커스텀 훅을 사용해보고, 만들어보는 시간을 갖도록 하겠습니다.
먼저 src 디렉터리에 hooks 라는 디렉터리를 만들고, 그 안에 useInputs.js 라는 파일을 만드세요. 훅을 만들 때 사용하는 규칙이 있는데, 보통 어떠한 훅 전에 use 라는 접두사를 붙이게 됩니다. 예를 들어 useState, useEffect, useReducer 등등 처럼 말이죠.
그러면 본격적으로 아래 내용을 통해 useInput.js 를 코딩하겠습니다. useInput.js
import { useState, useCallback } from "react";
function useInput(initialForm) {
const [inputs, setInputs] = useState(initialForm);
const onChange = useCallback((e) => {
var { name, value } = e.target;
setInputs({
...inputs,
[name]: value,
});
});
const reset = useCallback(() => {
setInputs(initialForm);
});
return [inputs, onChange, reset];
}
export default useInput;
useState를 통해 form 데이터를 가져올 것입니다. 그리고, onChange 메소드와 reset 메소드를 생성하여 외부의 여러 파일에서도 사용할 수 있게 하였습니다.
다음은 App.js 코드입니다.
import "./App.css";
import react, { useCallback, useReducer, useRef } from "react";
import UserList from "./UserList.js";
import CreateUser from "./CreateUser";
import useInput from "./hooks/useInput";
function App() {
const nextIndex = useRef(4);
function reducer(state, action) {
switch (action.type) {
case "CREATE_USER":
return {
users: state.users.concat(action.user),
};
case "TOGGLE_USER":
return {
users: state.users.map((user) => {
return user.id === action.userId ? { ...user, active: true } : user;
}),
};
case "DELETE_USER":
return {
users: state.users.filter((user) => {
return user.id !== action.userId;
}),
};
default:
break;
}
return state;
}
const initForm = { name: "", email: "" };
const [form, onChange, reset] = useInput(initForm);
const initialState = {
users: [
{ id: 0, name: "John", email: "john@gmail.com", active: true },
{ id: 1, name: "Smith", email: "smith@gmail.com", active: false },
{ id: 2, name: "Park", email: "park@gmail.com", active: false },
{ id: 3, name: "Kim", email: "kim@gmail.com", active: false },
],
};
const [state, dispatch] = useReducer(reducer, initialState);
const { users } = state;
const { name, email } = form;
const onClick = useCallback(() => {
dispatch({
type: "CREATE_USER",
user: {
id: nextIndex.current++,
name,
email,
active: false,
},
});
reset();
}, [users, name, email]);
const onToggle = useCallback(
(userId) => {
dispatch({
type: "TOGGLE_USER",
userId,
form,
});
},
[users]
);
const onDelete = useCallback(
(userId) => {
dispatch({
type: "DELETE_USER",
userId,
form,
});
},
[users]
);
return (
<div>
<CreateUser name={name} email={email} onChange={onChange} onClick={onClick} />
<UserList users={users} onToggle={onToggle} onDelete={onDelete} />
<div>활성화된 사용자 수 : 0</div>
</div>
);
}
export default App;
우리가 만든 useInput 이라는 Hook을 불러와서 setInput 메소드가 있었던 자리에 넣고, 이것 저것 수정한 결과입니다.
이렇게 커스텀 Hook 을 만들어서 사용하면 컴포넌트의 로직을 분리시켜서 필요 할 때 쉽게 재사용 할 수도 있습니다.
'오픈소스 > 노드' 카테고리의 다른 글
[Node] Immer 라이브러리를 이용하여 더 쉬운 불변성 관리 (0) | 2021.10.19 |
---|---|
[Node] React 정리(17) - Context API 를 사용한 전역 값 관리 (0) | 2021.10.19 |
[Node] React 정리(15) - useReducer를 사용한 코드 예제 (0) | 2021.10.19 |
[Node] React 정리(14) - useReducer를 사용하여 상태 업데이트 분리 (0) | 2021.10.19 |
[Node] React 정리(13) - React.memo을 사용하여 컴포넌트 리렌더링 방지 (0) | 2021.10.19 |