阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

63 個專案實戰,寫出作品集,讓面試官眼前一亮!

立即開始免費試讀!

自訂鉤子不僅僅是 React 中的一個便利性——它們也是模組化和可維護程式碼的遊戲規則改變者。它們允許開發人員以以前不可能的方式封裝邏輯、管理狀態並簡化複雜的功能。

圖片說明

React 強大的函數式程式設計範式重新定義了現代前端開發,為模組化、可維護和可重複使用的程式碼鋪平了道路。在其眾多功能中,自訂掛鉤作為建置更智慧、更清潔元件的關鍵推動者脫穎而出。今天,讓我們深入研究每個開發人員工具包中都應該擁有的一些基本自訂鉤子,並學習如何有效地實現它們。


  1. useFetch :簡化 API 呼叫 🌐

取得資料是 React 中常見的任務。 useFetch 鉤子抽象化了重複的邏輯,簡化了 API 呼叫並優雅地管理狀態。

執行:

import { useState, useEffect } from "react";

function useFetch<T>(url: string) {
  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<Error | null>(null);

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true);
      try {
        const response = await fetch(url);
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err as Error);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

export default useFetch;

用法:

const { data, loading, error } = useFetch<User[]>('/api/users');

if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;

return <ul>{data?.map(user => <li key={user.id}>{user.name}</li>)}</ul>;

  1. useDebounce :優化效能 ⏳

透過防手震鉤子可以有效處理頻繁的使用者輸入(例如搜尋或表單欄位),從而減少不必要的渲染和 API 呼叫。

執行:

import { useState, useEffect } from "react";

function useDebounce<T>(value: T, delay: number): T {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const handler = setTimeout(() => setDebouncedValue(value), delay);

    return () => clearTimeout(handler);
  }, [value, delay]);

  return debouncedValue;
}

export default useDebounce;

用法:

const [searchTerm, setSearchTerm] = useState('');
const debouncedSearch = useDebounce(searchTerm, 500);

useEffect(() => {
  if (debouncedSearch) {
    // Trigger API or other actions
  }
}, [debouncedSearch]);

  1. useToggle :輕鬆管理布林狀態

「使用自訂 useToggle 掛鉤可以輕鬆管理模態、下拉式選單或主題開關的切換狀態,從而保持程式碼整潔且可重複使用。

執行

import { useState } from "react";

function useToggle(initialState = false) {
  const [state, setState] = useState(initialState);

  const toggle = () => setState(prev => !prev);

  return [state, toggle] as const;
}

export default useToggle;

用法:

const [isModalOpen, toggleModal] = useToggle();

return (
  <div>
    <button onClick={toggleModal}>Toggle Modal</button>
    {isModalOpen && <p>Modal Content</p>}
  </div>
);

  1. useLocalStorage :在本地儲存資料 📂

透過自訂 useLocalStorage 掛鉤,從 localStorage 儲存和擷取資料變得無縫且可重複使用。

執行:

import { useState } from "react";

function useLocalStorage<T>(key: string, initialValue: T) {
  const [storedValue, setStoredValue] = useState<T>(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.error(error);
      return initialValue;
    }
  });

  const setValue = (value: T) => {
    try {
      setStoredValue(value);
      window.localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue] as const;
}

export default useLocalStorage;

用法:

const [theme, setTheme] = useLocalStorage('theme', 'light');

return (
  <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
    Toggle Theme
  </button>
);

  1. usePrevious :跟蹤之前的狀態 📜

追蹤值的先前狀態對於比較和動畫至關重要,可以透過自訂 usePrevious 掛鉤輕鬆實現。

執行:

import { useEffect, useRef } from "react";

function usePrevious<T>(value: T): T | undefined {
  const ref = useRef<T>();

  useEffect(() => {
    ref.current = value;
  }, [value]);

  return ref.current;
}

export default usePrevious;

用法:

const [count, setCount] = useState(0);
const prevCount = usePrevious(count);

return (
  <p>
    Now: {count}, Before: {prevCount}
  </p>
);

  1. useClickOutside :偵測外部點擊🖱️

非常適合在單擊外部時關閉模式或下拉式選單,使用自訂 useClickOutside 掛鉤以獲得更好的使用者體驗。

執行:

import { useEffect, useRef } from "react";

function useClickOutside(handler: () => void) {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (ref.current && !ref.current.contains(event.target as Node)) {
        handler();
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [handler]);

  return ref;
}

export default useClickOutside;

用法:

const ref = useClickOutside(() => setDropdownOpen(false));

return (
  <div ref={ref}>
    {dropdownOpen && <p>Dropdown Content</p>}
  </div>
);

  1. useMediaQuery :處理響應式設計📱

透過自訂 useMediaQuery 掛鉤,簡化了 React 中媒體查詢的管理,使響應式設計更有效率。

執行:

import { useState, useEffect } from "react";

function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const mediaQueryList = window.matchMedia(query);

    const updateMatch = () => setMatches(mediaQueryList.matches);
    updateMatch();

    mediaQueryList.addEventListener('change', updateMatch);
    return () => mediaQueryList.removeEventListener('change', updateMatch);
  }, [query]);

  return matches;
}

export default useMediaQuery;

用法:

const isMobile = useMediaQuery('(max-width: 768px)');

return <p>{isMobile ? 'Mobile View' : 'Desktop View'}</p>;

_自訂掛鉤展示了 React 的靈活性和強大功能,使程式碼更乾淨、可重複使用且更易於維護。

_

透過利用自訂掛鉤,開發人員可以簡化複雜的功能並建立可重複使用的高效程式碼。上面的例子展示了這些鉤子如何優雅地解決常見的挑戰。


我希望您覺得這有幫助!如果我們在LinkedIn上聯絡我會很高興 🚀


原文出處:https://dev.to/joodi/7-react-custom-hooks-i-always-use-as-a-front-end-developer-5i9


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。

阿川私房教材:
學 JavaScript 前端,帶作品集去面試!

63 個專案實戰,寫出作品集,讓面試官眼前一亮!

立即開始免費試讀!