728x90
반응형
컴포넌트를 만들다보면 반복되는 로직이 자주 발생하는데 그럴 때 커스텀 Hooks 를 만들어서 반복되는 로직을 쉽게 재사용 하는 방법을 알아보자
src에 hooks 라는 디렉토리를 만들고, 그 안에 useInputs 라는 파일을 만들자
*커스텀 Hooks 를 만들 때에는 보통 use 키워드로 시작하는 파일을 만들고 그 안에 함수를 작성함
안에서 useEffect, useReducer, useCallback 등 Hooks 를 사용하여 원하는 기능을 구현하고 컴포넌트에서 사용하고 싶은 값들을 반환 해주면 됌.
useInputs.js
import React, {useCallback, useState} from "react";
function useInputs(initialForm) {
const [form, setForm] = useState(initialForm);
// change
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;
이제 만든 Hook 을 App.js 에서 사용해보자
useReducer 쪽에서 사용하는 inputs 를 없애고 이에 관련된 작업을 useInputs 로 대체해줘야함
새로운 항목을 추가 할 때 input 값을 초기화해야해서 데이터 등록 후 reset() 을 호출해주자
App.js
import React, {useCallback, useMemo, useReducer, useRef} from 'react';
import CreateUser from './components/CreateUser';
import UserList from "./components/UserList";
import useInputs from "./hooks/useInputs";
function countActiveUsers(users) {
console.log("active 값이 ture 인 유저의 수를 센는중...");
return users.filter(user => user.active).length;
}
const initialState = {
users: [
{
id: 1,
username: 'velopert',
email: 'public.velopert@gmail.com',
active: true
},
{
id: 2,
username: 'tester',
email: 'tester@example.com',
active: false
},
{
id: 3,
username: 'liz',
email: 'liz@example.com',
active: false
}
]
};
// 불변성을 지켜주기 위해서 spread 연산자를 사용
function reducer(state, action) {
switch (action.type) {
case 'CREATE_USER' :
return {
inputs: initialState.inputs,
users: state.users.concat(action.user)
};
case 'TOGGLE_USER' :
return {
...state,
users: state.users.map(user =>
user.id === action.id ? {...user, active: !user.active } : user
)
};
case 'REMOVE_USER' :
return {
...state,
users: state.users.filter(user => user.id !== action.id)
};
default:
return state;
}
}
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
const { users } = state;
const [{ username, email }, onChange, reset] = useInputs({
username: '',
email: ''
});
const nextId = useRef(4);
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} key={users.id}/>
<div>활성 사용자 수 : {count}</div>
</>
);
}
export default App;
다 만들었으면 inputs Hook 을 useReducer 로 만들어보자 지금 만든건 useState 로 만들었음
useReducer 버전 (주석은 useState 버전)
import React, {useCallback, useReducer} from "react";
// function useInputs(initialForm) {
// const [form, setForm] = useState(initialForm);
//
// // change
// const onChange = useCallback(e => {
// const {name, value} = e.target;
// setForm(form => ({
// ...form,
// [name]: value
// }
// ));
// }, []);
//
// const reset = useCallback(() => setForm(initialForm), [initialForm]);
// return [form, onChange, reset];
// }
function reducer(state, action) {
switch (action.type) {
case 'CHANGE' :
return {
...state,
[action.name]: action.value
};
case 'RESET' :
return Object.keys(state).reduce((acc, current) => {
acc[current] = '';
return acc;
},{});
default :
return state;
}
}
function useInputs(initialForm) {
const [form, dispatch] = useReducer(reducer, initialForm);
// change
const onChange = useCallback(e => {
const {name, value} = e.target;
dispatch({
type: 'CHANGE',
name,
value
});
},[]);
const reset = useCallback(() =>
dispatch({
type: 'RESET'
}),[]);
return [form, onChange, reset];
}
export default useInputs;
728x90
반응형
'JS Library > React' 카테고리의 다른 글
| API 연동하기, axios (0) | 2022.06.09 |
|---|---|
| Immer 라이브러리 (0) | 2022.05.26 |
| Context API 전역 값 관리 (0) | 2022.05.26 |
| React.memo (0) | 2022.05.25 |
| useCallback 를 사용하여 함수 재사용 (0) | 2022.05.25 |
| React Developer Tools (0) | 2022.05.24 |