본문 바로가기

Web Tech/react

react 기본 - 17.커스텀 Hooks

커스텀 Hooks

반복되는 로직을 커스텀 Hooks 를 만들어서 로직을 쉽게 재사용하는 방법입니다.

보통 use라는 키워로 시작하는 파일을 만들고 그 안에 함수로 작성하여, 그 안에서 useState, useEffect, useReducer, useCallback 등 Hooks을 사용해서 원하는 기능 구현 후 컴포넌트에서 사용하고 싶은 값 반환하면 됩니다.

useInputs.js

import {useState, useCallback} from 'react';

function useInputs(initialForm) {
    const [form, setForm] = useState(initialForm);

    const onChage = useCallback(e => {
        const {name, value} = e.target;
        setForm(form => ({...form, [name]: value}));
    }, []);
	// 새로운 항복을 추가할 시 input 값 초기화
    const reset = useCallback(() => setForm(initialForm), [initialForm]);
    return [form, onChage,reset];
}

export default useInputs;

App.js

import React, {useRef, useReducer, useMemo, useCallback} from 'react';
import Inner from "./Inner";
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: 'a',
            email: 'a@aaa.com',
            active: true
        },
        {
            id: 2,
            username: 'b',
            email: 'b@bbb.com',
            active: false
        },
        {
            id: 3,
            username: 'c',
            email: 'c@ccc.com',
            active: false
        }
    ]
};

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 [{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 (
        <React.Fragment>
            <Inner>
                <CreateUser username={username} email={email} onChange={onChange} onCreate={onCreate}/>
                <UserList users={users} onToggle={onToggle} onRemove={onRemove}/>
                <p>활성사용자 수 : {count}</p>
            </Inner>
        </React.Fragment>
    );
}

export default App;

'Web Tech > react' 카테고리의 다른 글