日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

一起來了解React的Hook_React

作者:zju_cbw ? 更新時間: 2022-05-18 編程語言

State Hook

這個例子用來顯示一個計數器。當你點擊按鈕,計數器的值就會增加:

import React, { useState } from 'react';
function Example() {
  // 聲明一個叫 “count” 的 state 變量。
  const [count, setCount] = useState(0);
  return (
    

You clicked {count} times

); }

在這里,useState?就是一個 Hook (等下我們會講到這是什么意思)。通過在函數組件里調用它來給組件添加一些內部?state。React 會在重復渲染時保留這個?stateuseState?會返回一對值:當前狀態一個讓你更新它的函數,你可以在事件處理函數中或其他一些地方調用這個函數。它類似?class?組件的?this.setState,但是它不會把新的?state?和舊的?state?進行合并。(我們會在使用 State Hook 里展示一個對比?useState?和?this.state?的例子)。

useState?唯一的參數就是初始?state。在上面的例子中,我們的計數器是從零開始的,所以初始?state?就是?0。值得注意的是,不同于?this.state,這里的?state?不一定要是一個對象 —— 如果你有需要,它也可以是。這個初始?state?參數只有在第一次渲染時會被用到。

聲明多個 state 變量

你可以在一個組件中多次使用 State Hook:

function ExampleWithManyStates() {
  // 聲明多個 state 變量!
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: 'Learn Hooks' }]);
  // ...
}

數組解構的語法讓我們在調用?useState?時可以給?state?變量取不同的名字。當然,這些名字并不是?useState?API 的一部分。React 假設當你多次調用?useState?的時候,你能保證每次渲染時它們的調用順序是不變的。后面我們會再次解釋它是如何工作的以及在什么場景下使用。

那么,什么是 Hook?

Hook 是一些可以讓你在函數組件里 " 鉤入" React?state?及生命周期等特性的函數。Hook 不能在?class?組件中使用 —— 這使得你不使用?class?也能使用 React。(我們不推薦把你已有的組件全部重寫,但是你可以在新組件里開始使用 Hook。)

React 內置了一些像?useState?這樣的 Hook。你也可以創建你自己的 Hook 來復用不同組件之間的狀態邏輯。我們會先介紹這些內置的 Hook。

Effect Hook

你之前可能已經在 React 組件中執行過數據獲取、訂閱或者手動修改過 DOM。我們統一把這些操作稱為“副作用”,或者簡稱為“作用”。

useEffect?就是一個 Effect Hook,給函數組件增加了操作副作用的能力。它跟?class?組件中的?componentDidMountcomponentDidUpdate?和?componentWillUnmount?具有相同的用途,只不過被合并成了一個 API。

例如,下面這個組件在 React 更新 DOM 后會設置一個頁面標題:

import React, { useState, useEffect } from 'react';
function Example() {
  const [count, setCount] = useState(0);
  // 相當于 componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    // 使用瀏覽器的 API 更新頁面標題
    document.title = `You clicked ${count} times`;
  });
  return (
    

You clicked {count} times

); }

當你調用?useEffect?時,就是在告訴 React 在完成對 DOM 的更改后運行你的“副作用”函數。由于副作用函數是在組件內聲明的,所以它們可以訪問到組件的?props?和?state。默認情況下,React 會在每次渲染后調用副作用函數 ——?包括第一次渲染的時候。

副作用函數還可以通過返回一個函數來指定如何“清除”副作用。例如,在下面的組件中使用副作用函數來訂閱好友的在線狀態,并通過取消訂閱來進行清除操作:

import React, { 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';
}

在這個示例中,React 會在組件銷毀時取消對?ChatAPI?的訂閱,然后在后續渲染時重新執行副作用函數。(如果傳給?ChatAPI?的?props.friend.id?沒有變化,你也可以告訴 React 跳過重新訂閱。)

跟?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);
  }
  // ...

通過使用 Hook,你可以把組件內相關的副作用組織在一起(例如創建訂閱及取消訂閱),而不要把它們拆分到不同的生命周期函數里。

Hook 使用規則

Hook 就是 JavaScript 函數,但是使用它們會有兩個額外的規則:

  • 只能在函數最外層調用 Hook。不要在循環、條件判斷或者子函數中調用。
  • 只能在?React 的函數組件中調用 Hook。不要在其他 JavaScript 函數中調用。(還有一個地方可以調用 Hook —— 就是自定義的 Hook 中,我們稍后會學習到。)

自定義 Hook

有時候我們會想要在組件之間重用一些狀態邏輯。目前為止,有兩種主流方案來解決這個問題:高階組件和?render props。自定義 Hook 可以讓你在不增加組件的情況下達到同樣的目的。

前面,我們介紹了一個叫?FriendStatus?的組件,它通過調用?useState?和?useEffect?的 Hook 來訂閱一個好友的在線狀態。假設我們想在另一個組件里重用這個訂閱邏輯。

首先,我們把這個邏輯抽取到一個叫做?useFriendStatus?的自定義 Hook 里:

import React, { 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?作為參數,并返回該好友是否在線:

現在我們可以在兩個組件中使用它:

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 (
    
  • {props.friend.name}
  • ); }

    每個組件間的?state?是完全獨立的。Hook 是一種復用狀態邏輯的方式,它不復用?state?本身。事實上 Hook 的每次調用都有一個完全獨立的?state?—— 因此你可以在單個組件中多次調用同一個自定義 Hook。

    自定義 Hook 更像是一種約定而不是功能。如果函數的名字以?use?開頭并調用其他 Hook,我們就說這是一個自定義 Hook。?useSomething?的命名約定可以讓我們的?linter?插件在使用 Hook 的代碼中找到 bug。

    你可以創建涵蓋各種場景的自定義 Hook,如表單處理、動畫、訂閱聲明、計時器,甚至可能還有更多我們沒想到的場景。我們很期待看到 React 社區會出現什么樣的自定義 Hook。

    其他 Hook

    除此之外,還有一些使用頻率較低的但是很有用的 Hook。比如,useContext?讓你不使用組件嵌套就可以訂閱 React 的 Context。

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

    另外?useReducer?可以讓你通過?reducer?來管理組件本地的復雜?state

    function Todos() {
      const [todos, dispatch] = useReducer(todosReducer);
      // ...
    

    總結

    原文鏈接:https://blog.csdn.net/weixin_44491423/article/details/123506737

    欄目分類
    最近更新