[React] Custom Hooks

Dongmin Lee·2023년 2월 22일

React

목록 보기
4/11

💿 이 글의 목적

💿 관심사의 분리(SoC, Separation of Concerns)

한 번에 하나의 걱정만!

관심사의 분리란 단위 별로 하나의 관심사만 있도록 분리하는 과정.

💾 KISS(Keep It Simple, Stupid)

코드는 짧고 간단해야 한다!

코드가 단순해질수록 재사용이 쉽고, 유지보수가 용이해지고, 테스트 코드 작성이 간단해짐.

💾 나쁜 예시

const loginForm = document.getElementsByClassName('loginForm')[0];
const loginBtn = document.getElementById('loginBtn');

const handleInput = () => {
  const idValue = document.getElementById('id').value;
  const pwValue = document.getElementById('pw').value;

  const isIdValid = idValue.length > 1;
  const isPasswordValid = pwValue.length > 1;
  const isLoginInputValid = isIdValid && isPasswordValid;

  loginBtn.disabled = !isLoginInputValid;
  loginBtn.style.opacity = isLoginInputValid ? 1 : 0.3;
  loginBtn.style.cursor = isLoginInputValid ? 'pointer' : 'default';
};

const init = () => {
  loginForm.addEventListener('input', handleInput);
};

init();

handleInput 함수 내에 너무 많은 기능이 들어있다.

💾 좋은 예시

const loginForm = document.getElementsByClassName('loginForm')[0];
const loginBtn = document.getElementById('loginBtn');

const validateForm = () => {                                               // 1
  const idValue = document.getElementById('id').value;
  const pwValue = document.getElementById('pw').value;

  const isIdValid = idValue.length > 1;
  const isPasswordValid = pwValue.length > 1;

  return isIdValid && isPasswordValid;
}

const handleButtonActive = (isButtonActive) => {                           // 2
  loginBtn.disabled = !isButtonActive;
  loginBtn.style.opacity = isButtonActive ? 1 : 0.3;
  loginBtn.style.cursor = isButtonActive ? 'pointer' : 'default';
}

const handleLoginInput = () => {                                           // 3
  const isFormValid = validateForm();
  handleButtonActive(isFormValid);
}

const init = () => {
  loginForm.addEventListener('input', handleLoginInput);
};

init();

기존의 handleInput을 기능별로 세분화하였다.

💿 Custom Hooks

기존에 사용하던 훅인 useState 나 useEffect 또한 React의 내장 메소드이다.
상태 관리를 위해 훅을 사용했던 것처럼, fetch처럼 Hook을 사용하고 재사용이 잦은 기능을 커스터마이징하여 컴포넌트처럼 사용하는 것이 커스텀 훅이다.

useFetch 이런거 겁나 편해보임..

💾 예시

// UserStatus.js

import React, { useState } from 'react';

const UserStatus = () => {
  const [isActive, setIsActive] = useState(false);

  const handleToggle = () => {
    setIsActive((prev) => !prev);
  };

  return (
    <>
      <h1>현재 사용자의 상태입니다.</h1>
      <span>{isActive ? '사용 중' : '사용 안 함'}</span>
      <button onClick={handleToggle}>사용 상태 변경</button>
    </>
  );
};

export default UserStatus;

해당 코드는 로직과 UI가 결합되어 있다.

// UserStatus.js

import React, { useState } from 'react';

const useToggle = (initialValue = false) => {                     // 1
  const [state, setState] = useState(initialValue);               // 2

  const handleToggle = () => {                                    // 3
    setState((prev) => !prev);
  };

  return [state, handleToggle];                                   // 4
};

const UserStatus = () => {                                      
  const [isActive, changeStatus] = useToggle();                   // 5

  return (
    <>
      <h1>현재 사용자의 상태입니다.</h1>
      <span>{isActive ? '사용 중' : '사용 안 함'}</span>              // 6
      <button onClick={changeStatus}>사용 상태 변경</button>
    </>
  );
};

export default UserStatus;

UserStatus 컴포넌트에서 토글 기능을 useToggle 이라는 함수로 빼냈다. 재사용성이 높아보이니 이 함수를 커스텀 훅으로 활용해주자.

// useToggle.js

import { useState } from 'react';

const useToggle = (initialValue = false) => {
  const [state, setState] = useState(initialValue);

  const handleToggle = () => {
    setState((prev) => !prev);
  };

  return [state, handleToggle];
};

export default useToggle;

useToggle.js 파일을 생성해 토글 기능을 분리해주었다.

// UserStatus.js

import React from 'react';
import useToggle from './useToggle';

const UserStatus = () => {
  const [isActive, changeStatus] = useToggle();

  return (
    <>
      <h1>현재 사용자의 상태입니다.</h1>
      <span>{isActive ? '사용 중' : '사용 안 함'}</span>
      <button onClick={changeStatus}>사용 상태 변경</button>
    </>
  );
};

export default UserStatus;

결과적으로 useState를 사용했을 때처럼 디스트럭쳐링해서 사용하게 된다.

💿 Reference

wecode 세션

🐍 뱀발

이해는 어렵지 않지만 활용이 어려워보인다. 많이 써봐야겠다.

profile
어제보다 성장하기

0개의 댓글