React自定義Hook深入解析

React是一個可重複使用的UI組件庫,而自定義Hook讓我們可以使用自己的邏輯來將一些行為等移到可重複使用的函數中,方便代碼的復用和組合。

一、Hook的簡介

React Hook是在React16.8版本新增的一項特性。它允許您在不編寫 Class 組件的情況下使用狀態(state)和其它 React 特性。它們是一個允許您在函數組件中添加狀態和其他React功能的方法。

使用hooks,就可以在不編寫Class組件的情況下,使用狀態(state)等react特性, 無需改變組件的層級,更容易的實現復用和組合。

二、何為自定義Hook?

自定義hook使得你可以使用功能組件實現狀態邏輯復用。自定義hook是一個函數,命名以use為前綴,函數內部可以調取別的hook。自定義hook可以將組件的狀態邏輯提取到可重用的函數中。


function useCustomHook() {
  //調用state或Effect等hook
  const [count, setCount] = useState(0);
  useEffect(() => {
    //登場效果
  });
  //自定義函數
  function handleCount() {
    setCount(count + 1);
  }
  //返回數據
  return {
    count,
    handleCount,
  };
}
function CustomComponent() {
  //調用自定義hook
  const { count, handleCount } = useCustomHook();
  //返回展示效果
  return (
    <div>
      <p>The count is {count}</p>
      <button onClick={handleCount}>Click me</button>
    </div>
  );
}

三、實現業務邏輯分離

使用自定義hook使得我們可以把共同的業務邏輯放在一起。例如,當我們需要處理本地存儲的請求時,無需在每一個需要本地存儲的組件重複去寫hook獲取存儲值。

下面是一個實現LocalStorage邏輯分離的例子:


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

  const setValue = (value) => {
    try {
      const valueToStore =
        value instanceof Function ? value(storedValue) : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.log(error);
    }
  };

  return [storedValue, setValue];
}

function CustomComponent() {
  const [name, setName] = useLocalStorage("name", "");
  //返回展示效果
  return (
    <div>
      <p>My name is {name}</p>
      <button onClick={() => setName("John Doe")}>Set name to John Doe</button>
    </div>
  );
}

四、組件與非組件hook的區別

自定義hook既可以作為組件的hook使用,也可以是非組件的hook。不過對於組件hook與非組件hook在實現上有一定的區別:

  • 組件hook可以依賴參數進行更新,除此之外的非組件hook是用來實現通用邏輯。
  • 組件hook可以返回待渲染的JSX,而非組件hook則是返回狀態和操作函數。

//組件hook
function useScrollTop() {
  const [scrollTop, setScrollTop] = useState(false);
  useEffect(() => {
    function handleScroll() {
      setScrollTop(window.scrollY > 0);
    }
    document.addEventListener('scroll', handleScroll);
    return () => {
      document.removeEventListener('scroll', handleScroll);
    }
  }, []);
  return <div style={{ position: 'fixed', top: '18px', right: '30px' }}>{scrollTop&&<a href="#top">UP</a>}</div>;
}

//非組件hook
function useNotification(title, options) {
  if (!("Notification" in window)) {
    return;
  }
  const [permission] = useState(Notification.permission);
  const [notification, setNotification] = useState(null);

  const handleNotification = () => {
    const notification = new Notification(title, options);
    setNotification(notification);
  };

  const checkNotificationPromise = () => {
    try {
      Notification.requestPermission().then();
    } catch (e) {
      return false;
    }
    return true;
  };

  const requestNotificationPermission = async () => {
    if (permission === "granted") {
      handleNotification();
    } else if (permission !== "denied") {
      const permission = await Notification.requestPermission();
      if (permission === "granted") {
        handleNotification();
      }
    }
  };

  useEffect(() => {
    if (permission === "granted") {
      requestNotificationPermission();
    } else if (permission === "default") {
      checkNotificationPromise();
    }
    return () => {
      if (notification) {
        notification.close();
      }
    };
  }, []);
}

五、自定義Hook對流程式控制制的影響

自定義hook聚焦於某些行為,以讓組件對他們進行使用而不需要關心實現細節。自定義hook讓組件更容易組合、共享行為,而無需關心時間的實現細節。

而對於每一個使用Effect的組件,都需要在componentDidMount和componentDidUnMount中組合其中的一些行為。這些代碼很容易出錯、難以閱讀、難以恢復,並且難以測試。

自定義Hook讓我們可以將這種代碼和行為分離,同時讓我們的組件不那麼臃腫。自定義Hook可以針對一個特定的行為,而不是一個組件,從而更好地實現復用和組合。

六、結語

自定義hook使得我們可以將代碼結構更加清晰和易於復用。從我們的應用程序中抽象出類似於useEffect、useState、useRef和useReducer的概念,並使用它們構建更高層次的抽象,可以更好地表達我們的意圖,發現隱式複雜性。

在任何情況下,請記住重構代碼並不總是意味著把所有東西重新設計到新的地方。根據需要使用自定義hook或者組件可以使代碼更易於維護和擴展。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/242242.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:48
下一篇 2024-12-12 12:48

相關推薦

  • @uiw/react-amap介紹

    本文將詳細闡述@uiw/react-amap的使用方法和參數配置,以及如何在React應用中集成高德地圖組件。 一、@uiw/react-amap簡介 @uiw/react-ama…

    編程 2025-04-29
  • Python中自定義函數必須有return語句

    自定義函數是Python中最常見、最基本也是最重要的語句之一。在Python中,自定義函數必須有明確的返回值,即必須要有return語句。本篇文章將從以下幾個方面對此進行詳細闡述。…

    編程 2025-04-29
  • Python自定義列表

    本文將為大家介紹Python中自定義列表的方法和應用場景。對自定義列表進行詳細的闡述,包括列表的基本操作、切片、列表推導式、列表的嵌套以及列表的排序,希望能夠幫助大家更好地理解和應…

    編程 2025-04-27
  • Webrtc音視頻開發React+Flutter+Go實戰PDF

    本文將從多個方面介紹如何使用React、Flutter和Go來進行Webrtc音視頻開發,並提供相應的代碼示例。 一、Webrtc音視頻開發介紹 Webrtc是Google開發的一…

    編程 2025-04-27
  • 如何添加Python自定義模塊?

    Python是一種非常流行的腳本語言,因其易學易用和功能強大而備受歡迎。自定義模塊是Python開發中經常使用的功能之一。本文將從多個方面為您介紹如何添加Python自定義模塊。 …

    編程 2025-04-27
  • React簡書項目

    本文將從以下幾個方面介紹React簡書項目: 項目概述 組件分析 路由配置 Redux狀態管理 項目優化 一、項目概述 React簡書項目是一個類似於博客的Web應用,提供用戶撰寫…

    編程 2025-04-27
  • 深入解析Vue3 defineExpose

    Vue 3在開發過程中引入了新的API `defineExpose`。在以前的版本中,我們經常使用 `$attrs` 和` $listeners` 實現父組件與子組件之間的通信,但…

    編程 2025-04-25
  • 深入理解byte轉int

    一、位元組與比特 在討論byte轉int之前,我們需要了解位元組和比特的概念。位元組是計算機存儲單位的一種,通常表示8個比特(bit),即1位元組=8比特。比特是計算機中最小的數據單位,是…

    編程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什麼是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一個內置小部件,它可以監測數據流(Stream)中數據的變…

    編程 2025-04-25
  • 深入探討OpenCV版本

    OpenCV是一個用於計算機視覺應用程序的開源庫。它是由英特爾公司創建的,現已由Willow Garage管理。OpenCV旨在提供一個易於使用的計算機視覺和機器學習基礎架構,以實…

    編程 2025-04-25

發表回復

登錄後才能評論