React Hook(自定義 Hook)


前沿

想寫下react hooks ,一些基本資料,當然也可以看官網,我只是整理下

 react hooks 的官方基本介紹可以看 React 的文檔:https://reactjs.org/docs/hooks-intro.html

一、State Hook

以一個簡單的計數器舉例,使用 useState 這個 Hook:

import { useState } from 'react';
function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

上面的 useState 實際上就是一個 Hook,我們在函數組件中調用它來向它添加一些本地的 state,而 React 在 re-render 之前會保留這個 state。useState 返回兩個內容:

  • 當前的 state 值
  • 一個允許更新 state 值的 function

可以從事件處理程序或者其他位置調用返回的 function,和類中的 this.setState 比較累色,只不過不會將新的 state 和舊的 state 合並在一起。(React 給過一個使用 useState 和 this.state 的比較的示例https://reactjs.org/docs/hooks-state.html

useState 的唯一參數是初始狀態,在上面的例子中,初始 state 是 0,因為計數器從 0 開始。請注意,和 this.state 不同的是,這里的 state 不一定是對象,可以是隨便需要的形式。而初始狀態參數僅僅在第一次渲染的時候使用。

 

1、聲明多個 state 變量

可以在單個組件中多次使用 state Hook:

function ExampleWithManyStates() {
  // Declare multiple state variables!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}

數組結構語法允許給 useState 的聲明的 state 變量賦予不同的名稱,這些名稱並不是 useState API 的一部分。相反,React 假定如果多次調用 useState,則在每次渲染期間,以相同的順序執行。

2、什么是 Hook

Hook 是允許從功能組件 掛鈎 React 的 state 和生命周期方法等功能。Hook 在類的內部不起作用——允許在沒有類的情況下使用 React。(React 不建議全部重寫組件,只是建議如果感興趣 Hook,可以在新的組件中使用)

React 提供了一些像 useState 這樣的內置 Hook,還可以創建自己的 Hook 以便於重用不同組件之間的狀態行為。

 

二、Effect Hook

我們已經可以在 React 組件中進行數據請求、subscriptions 或者是手動更改 DOM。

這些操作都是稱為 side effects,也就是副作用。因為它們會影響其他組件,並且在渲染過程中沒有辦法完成。

useEffect 增加了從功能組件執行副作用的功能。它與 React 類的 componentDidMountcomponentDidUpdate 和 componentWillUnmount 具有相同的效果,但是統一成了一個 API。可以在 Using the Effect Hool 文檔中查找關於更多 useEffect 的內容。

例如,下面的組件在 React 更新 DOM 后設置文檔標題:

import { useState, useEffect } from 'react';
function Example() {
  const [count, setCount] = useState(0);
  // Similar to componentDidMount and componentDidUpdate:
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
  });
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}
當調用 useEffect 的時候,告訴 React 在刷新對 DOM 的更改后運行 effect 副作用方法。因為 副作用方法 是在組件中聲明的,因此可以訪問 props 和 state。

默認情況下, React 在每次渲染后執行 effect 方法 —— 包括第一次渲染。想查看和生命周期方法的比較,也可以在 Using the Effect Hool 文檔中找到。

同時 effect 副作用方法可以通過返回函數指定如何 “清理” 它們。例如,下面組件使用效果來訂閱好友的在線 state,並通過取消訂閱來實現清理的目的:

import { useState, useEffect } from 'react';

function FriendStatus(props) {
  const [isOnline, setIsOnline] = useState(null);
  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}

 

在這個示例中,組件卸載或者是由於后面的 re-render 而重新執行副作用方法之前,React 會取消訂閱 ChatAPI。當然,如果 props 傳過來的 id 是沒有變化的,也可以通過某種方式來跳過訂閱和取消訂閱的行為:https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects

和 useState 一樣,可以在組件中使用多個 useEffect

function FriendStatusWithCounter(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });
  const [isOnline, setIsOnline] = useState(null);
  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  // ...

Hooks 允許通過哪些部分相關(比如添加和刪除訂閱)來組織組件中的副作用,而不是基於生命周期方法進行強制拆分。

三、 Hooks 的規則

Hooks 是 JavaScript 方法, 但它們強加了兩個額外的規則:

  • 只能在頂層調用 Hooks,不能再循環、條件或者是嵌套方法中調用 Hooks。
  • 僅在 React 功能組件中使用 Hooks。不能再常規的 JavaScript 方法中調用 Hook。

React 提供了一個 linter 插件 來自動執行這些規則。雖然這些規則可能會讓開發者比較首先,但是對於 Hooks 的良好運行至關重要。

四、構建自己的 Hook

有時,可能會希望在組件之間重用一些 state 的邏輯,一般之前的做法都是通過高階組件或者是 render props 來解決。自定義 Hook 能夠做到這種需求,而不需要向 tree 中增加更多組件。

前面雖然介紹了 useState 和 useEffect 來訂閱朋友的在線狀態,如果還希望在另一個組件中重用訂閱邏輯,首先需要將這個邏輯提取到一個名為 useFriendStatus 的自定義 Hook 中:

import { useState, useEffect } from 'react';
function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);
  function handleStatusChange(status) {
    setIsOnline(status.isOnline);
  }
  useEffect(() => {
    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });
  return isOnline;
}

 

這個方法參數是 friendID ,返回的是好友是否在線。

而現在可以在兩個組件中直接使用這個 Hook:

function FriendStatus(props) {
  const isOnline = useFriendStatus(props.friend.id);
  if (isOnline === null) {
    return 'Loading...';
  }
  return isOnline ? 'Online' : 'Offline';
}
function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);
  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

 

這些組件的狀態是完全獨立的,Hook 是重用有 state 邏輯的一種方式,而不是重用 state 本身。事實上,每次調用 Hook 都會有個完全隔離的狀態。因此可以在一個組件中使用相同的自定義 Hook 兩次。

自定義 Hook 更像是一種約定,而不是一種功能。如果函數的名字以 use 開頭,並且調用了其他的 Hook,則就稱其為一個自定義 Hook。useSomething 命名約定是為了 linter 插件在代碼中查找錯誤。

五、其他的 Hooks

除了上面的 useState 和 useEffect 之外,還有一些其他不太常用的 Hook 也可能很有用。比如 useContext 允許訂閱 React 上下文,不去引入嵌套。

function Example() {
  const locale = useContext(LocaleContext);
  const theme = useContext(ThemeContext);
  // ...
}

而 useReducer 允許使用 reducer 管理復雜的組件 state:

 
        
function Todos() {
  const [todos, dispatch] = useReducer(todosReducer);
  // ...
 
        
就簡答的介紹下HOOK吧,在數據請求的時候還是用到很多的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM