컴포넌트를 만들다보면, 종종 반복되는 로직들이 발생한다.
-> ex) input
을 관리하는 코드는 자주 작성할 수 있는 코드이다.
const onChange = (e) =>{
const {name, value} = e.target;
setInputs({...input, [name]:value});
}
-> input
을 관리하려면 e.target
안에 들어 있는 name
값이랑value
를 읽어서 참조해서 어떤 새로운 상태를 설정해야 함.
-> 이런 경우 커스텀 Hook를 만들어서 사용할 수 있다! ( = 나만의 Hook를 만든다.)
커스텀 Hooks 를 만드는 방법은 간단하다.
-> react안에 내장된useState
, useEffect
, useReducer
, useCallback
등과 같은 Hooks 를 사용하여 원하는 기능을 구현하고, 컴포넌트에서 사용하고 싶은 값들을 반환해주면 된다.
-> 반환하는 것들은 마음대로 할 수 있다.
커스텀 Hooks 를 만들 때에는 보통 use
+ 구현할 기능 단어로 된 이름의 파일을 만들고 그 안에 함수를 작성한다.
useInputs.js
import { useState, useCallback } from 'react';
function useInputs(initialForm) {
const [form, setForm] = useState(initialForm);
// onChange
const onChange = useCallback(e => {
const { name, value } = e.target;
setForm(form => ({ ...form, [name]: value }));
}, []);
const reset = useCallback(() => setForm(initialForm), [initialForm]);
return [form, onChange, reset];
}
export default useInputs;
useInputs
를 사용할 때는!함수에서 관리하는 form
에 대하여 초기 값을 파라미터로 받아온 다음에, hook이 반환하는 onChange
를 사용해서 input
의 change이벤트
를 관리하면 된다.
상태는 form
에서 조회.
초기화 하고 싶다면 reset
을 호출하면 된다.
useInputs.js
📍
useState
,useCallback
불러오기import { useState, useCallback } from 'react';
📍
useInputs
함수 생성.function useInputs(initialForm){ }
->
initialForm
: 해당input
form에서 관리할 초기값
📍
useState
사용function useInputs(initialForm) { const [form, setForm] = useState(initialForm);
->
form
이라는 새로운 상태 선언.
-> 초기값 : 파라미터로 가져온initialForm
📍
onChange
함수 생성const onChange = useCallback(e => { const { name, value } = e.target; setForm(form => ({ ...form, [name]: value })); // form 업데이트 }, []); // 의존하는 상태 없으므로 Deps 비워줌
📍
reset
함수 생성
:form
을 초기화 시키는 역할을 하는 함수.const reset = useCallback(() => setForm(initialForm), [initialForm]); // 파라미터로 가져온 것을 사용하고 있으니까 Deps 배열에 initialForm넣어 주기. return [form, onChange, reset];
📍 반환
return [form, onChange, reset]; // 세가지 값을 반환
-> 객체 형태로 내보내도 되고, 배열 형태로 내보내도 됨.
📍 내보내기
export default useInputs;
-> 해당 함수를 다른 곳에서 불러와서 쓸 수 있도록
export
해주기.
App.js
import React, { useRef, useReducer, useMemo, useCallback } from 'react';
import UserList from './UserList';
import CreateUser from './CreateUser';
import useInputs from './hooks/useInputs';
function countActiveUsers(users) {
console.log('활성 사용자 수를 세는중...');
return users.filter(user => user.active).length;
}
const initialState = {
users: [
{
id:1,
username: 'gyomni',
email: 'hi1@gmail.com',
active:true,
},
{
id:2,
username: 'joy',
email: 'hi2@gmail.com',
active:false,
},
{
id:3,
username: 'zoe',
email: 'hi3@gmail.com',
active:false,
}
]
};
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 =>
user.id === action.id ? { ...user, active: !user.active } : user
)
};
case 'REMOVE_USER':
return {
users: state.users.filter(user => user.id !== action.id)
};
default:
return state;
}
}
function App() {
const [{ username, email }, onChange, reset] = useInputs({
username: '',
email: ''
});
const [state, dispatch] = useReducer(reducer, initialState);
const nextId = useRef(4);
const { users } = state;
const onCreate = useCallback(() => {
dispatch({
type: 'CREATE_USER',
user: {
id: nextId.current,
username,
email
}
});
reset();
nextId.current += 1;
}, [username, email, reset]);
const onToggle = useCallback(id => {
dispatch({
type: 'TOGGLE_USER',
id
});
}, []);
const onRemove = useCallback(id => {
dispatch({
type: 'REMOVE_USER',
id
});
}, []);
const count = useMemo(() => countActiveUsers(users), [users]);
return (
<>
<CreateUser
username={username}
email={email}
onChange={onChange}
onCreate={onCreate}
/>
<UserList users={users} onToggle={onToggle} onRemove={onRemove} />
<div>활성사용자 수 : {count}</div>
</>
);
}
export default App;
App.js
📍
useInputs
불러오기import useInputs from './hooks/useInputs';
📍 초기값 지정.
const [{ username, email }, onChange, reset] = useInputs({ username: '', email: '' });
만들어 놓은
useInputs
를 보면 ↓↓↓return [form, onChange, reset];
-> 내보내 주는 순서 확인
-> 내보낼 때 이름은 아무렇게나 해도 상관 없음.
-> 첫번째 항목 :상태 / 두번째 항목 :onChange
이벤트 / 세번째 항목 : 초기화 함수
학습 : 벨로퍼트와 함께 하는 모던 리엑트