Custom Hooks

  • useState, useContext, useEffect ๋“ฑ์˜ Hook๋„ ์œ ์šฉํ•˜์ง€๋งŒ, ๊ธฐ์กด์˜ hook๊ณผ ํ•จ๊ป˜ ๊ตฌ์ฒด์ ์ธ ๋กœ์ง์„ ํŠน์ • ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ์ฒด์ ์ธ Hook์˜ ํ•„์š”์„ฑ

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๋Š” ์ž์‹ ๋งŒ์˜ Hook

  • Hook์˜ ์ด๋ฆ„์€ use + ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•œ๋‹ค(์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ)

์ƒํƒœ์™€ ์ƒํƒœ ์ €์žฅ ๋กœ์ง์„ ๊ณต์œ 

  • CustomHook์€ ์ƒํƒœ์™€์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋Š” ๋กœ์ง์„ ํ•จ๊ป˜ ์ €์žฅํ•˜๊ณ  ์ œ๊ณต

  • ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๋…๋ฆฝ์ ์œผ๋กœ ์‚ฌ์šฉ๊ฐ€๋Šฅ

import { Dispatch, SetStateAction, useCallback, useState } from 'react'

const useToggle = (defaultValue?: boolean = false): [boolean, () => void,Dispatch<SetStateAction<boolean>>] => {
  const [value, setValue] = useState(defaultValue)

  const toggle = useCallback(() => setValue(x => !x), [])

  return [value, toggle, setValue]
}

Hook์„ ์‚ฌ์šฉํ•˜๋ฉด Hook

  • ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ •์˜ ํ•จ์ˆ˜๊ฐ€ CustomHook์€ ์•„๋‹ˆ๋‹ค

  • ํ•จ์ˆ˜ ๋‚ด๋ถ€์— ํ•˜๋‚˜ ์ด์ƒ์˜ Hook์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ Custom Hook์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค

import { useState, ChangeEvent, HTMLProps } from 'react';

export function useFormInput(initialValue: string): {
  value: string;
  onChange: (e: ChangeEvent<HTMLInputElement>) => void;
} {
  const [value, setValue] = useState(initialValue);

  function handleChange(e: ChangeEvent<HTMLInputElement>) {
    setValue(e.target.value);
  }

  const inputProps: HTMLProps<HTMLInputElement> = {
    value: value,
    onChange: handleChange,
  };

  return inputProps;
}

Hook์œผ๋กœ ๋ถ„๋ฆฌํ•˜๊ธฐ

  • useEffect ๋ถ€๋ถ„์€ roomId, serverUrl ์˜ react ๊ฐ’์„ ํ†ตํ•ด ์ƒˆ๋กœ์šด ์—ฐ๊ฒฐ์„ ๋งŒ๋“ ๋‹ค.

  • ์ด๋ ‡๊ฒŒ hook์„ ์‚ฌ์šฉํ•˜๋Š” ๋กœ์ง์„ ์ปค์Šคํ…€ ํ›…์œผ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';
import { showNotification } from './notifications.js';

export default function ChatRoom({ roomId }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.on('message', (msg) => {
      showNotification('New message: ' + msg);
    });
    connection.connect();
    return () => connection.disconnect();
  }, [roomId, serverUrl]);

  return (
    <>
      <label>
        Server URL:
        <input value={serverUrl} onChange={e => setServerUrl(e.target.value)} />
      </label>
      <h1>Welcome to the {roomId} room!</h1>
    </>
  );
}
  • roomId, serverUrl์„ ์ดˆ๊ธฐ ๊ฐ’์œผ๋กœ ๋ฐ›๋Š” ์ปค์Šคํ…€ ํ›…์œผ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

export function useChatRoom({ serverUrl, roomId }) {
  useEffect(() => {
    const options = {
      serverUrl: serverUrl,
      roomId: roomId
    };
    const connection = createConnection(options);
    connection.connect();
    connection.on('message', (msg) => {
      showNotification('New message: ' + msg);
    });
    return () => connection.disconnect();
  }, [roomId, serverUrl]);
}
  • useChatRoom์€ chatRoom์„ ์—ฐ๊ฒฐํ•˜๋Š” ์„ธ๋ถ€ ๋กœ์ง์„ ์ˆจ๊ธฐ๊ณ  ์ž…๋ ฅ์œผ๋กœ roomId์™€ serverUrl๋งŒ ๋ฐ›๋Š”๋‹ค.

  • ์ด์ œ chatRoom์„ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ useChatRoom()์— roomId์™€ serverUrl๋งŒ ์ž…๋ ฅ์œผ๋กœ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค.

  useChatRoom({
    roomId: roomId,
    serverUrl: serverUrl
  });

์ปค์Šคํ…€ ํ›…์—์„œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋ถ„๋ฆฌ

import { useSyncExternalStore } from 'react';

function subscribe(callback) {
  window.addEventListener('online', callback);
  window.addEventListener('offline', callback);
  return () => {
    window.removeEventListener('online', callback);
    window.removeEventListener('offline', callback);
  };
}

export function useOnlineStatus() {
  return useSyncExternalStore(
    subscribe,
    () => navigator.onLine, // How to get the value on the client
    () => true // How to get the value on the server
  );
}

์ฃผ์˜ ์‚ฌํ•ญ

๊ธฐ๋ณธ Hook ์ž์ฒด์— ๋Œ€ํ•œ ๋ž˜ํผ hook ์ง€์–‘

  • useEffect์—์„œ ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰ํ•˜๋Š” ์ปค์Šคํ…€ ํ›…์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์•„๋ž˜์˜ useMount๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค

  • ํ•ด๋‹น ํ›…์œผ๋กœ ๋“ค์–ด์˜ค๋Š” fn ํ•จ์ˆ˜ ๋‚ด๋ถ€์—๋Š” ์–ด๋– ํ•œ react ๊ฐ’๋“ค์ด ์žˆ์„์ง€ ๋ชจ๋ฅธ๋‹ค.

  • ํ•˜์ง€๋งŒ useEffect๋Š” ์˜์กด์„ฑ ๋ฐฐ์—ด์ด ๋นˆ ๋ฐฐ์—ด์ด๊ธฐ ๋•Œ๋ฌธ์— react ๊ฐ’๋“ค์— ๋ฐ˜์‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.

// โŒ fn ํ•จ์ˆ˜์— ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉํ•˜๋Š” react ๊ฐ’์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์Œ
const useMount = (fn) => {
  useEffect(() => {
    fn();
  }, []); 
}

Last updated