커스텀 Hooks 생성

gyomni·2022년 2월 25일
0

React

목록 보기
8/9
post-thumbnail

custom hooks

  • 컴포넌트를 만들다보면, 종종 반복되는 로직들이 발생한다.
    -> 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 를 사용하여 원하는 기능을 구현하고, 컴포넌트에서 사용하고 싶은 값들을 반환해주면 된다.
    -> 반환하는 것들은 마음대로 할 수 있다.


input 상태를 관리하는 커스텀 hook 만들기~~!

커스텀 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를 사용해서 inputchange이벤트를 관리하면 된다.

  • 상태는 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이벤트 / 세번째 항목 : 초기화 함수

학습 : 벨로퍼트와 함께 하는 모던 리엑트

profile
Front-end developer 👩‍💻✍

0개의 댓글