React Hooks的理解


 

 

一、是什么

Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性

至於為什么引入hook,官方給出的動機是解決長時間使用和維護react過程中常遇到的問題,例如:

  • 難以重用和共享組件中的與狀態相關的邏輯
  • 邏輯復雜的組件難以開發與維護,當我們的組件需要處理多個互不相關的 local state 時,每個生命周期函數中可能會包含着各種互不相關的邏輯在里面
  • 類組件中的this增加學習成本,類組件在基於現有工具的優化上存在些許問題
  • 由於業務變動,函數組件不得不改為類組件等等

在以前,函數組件也被稱為無狀態的組件,只負責渲染的一些工作

因此,現在的函數組件也可以是有狀態的組件,內部也可以維護自身的狀態以及做一些邏輯方面的處理

二、有哪些

上面講到,Hooks讓我們的函數組件擁有了類組件的特性,例如組件內的狀態、生命周期

最常見的hooks有如下:

  • useState
  • useEffect
  • 其他

useState

首先給出一個例子,如下:

import React, { useState } from 'react';

function Example() {
  // 聲明一個叫 "count" 的 state 變量
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

在函數組件中通過useState實現函數內部維護state,參數為state默認的值,返回值是一個數組,第一個值為當前的state,第二個值為更新state的函數

該函數組件等價於的類組件如下:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

從上述兩種代碼分析,可以看出兩者區別:

  • state聲明方式:在函數組件中通過 useState 直接獲取,類組件通過constructor 構造函數中設置

  • state讀取方式:在函數組件中直接使用變量,類組件通過this.state.count的方式獲取

  • state更新方式:在函數組件中通過 setCount 更新,類組件通過this.setState()

總的來講,useState 使用起來更為簡潔,減少了this指向不明確的情況

useEffect

useEffect可以讓我們在函數組件中進行一些帶有副作用的操作

同樣給出一個計時器示例:

class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Click me
        </button>
      </div>
    );
  }
}

從上面可以看見,組件在加載和更新階段都執行同樣操作

而如果使用useEffect后,則能夠將相同的邏輯抽離出來,這是類組件不具備的方法

對應的useEffect示例如下:

import React, { useState, useEffect } from 'react';
function Example() {
  const [count, setCount] = useState(0);
 
  useEffect(() => {    document.title = `You clicked ${count} times`;  });
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useEffect第一個參數接受一個回調函數,默認情況下,useEffect會在第一次渲染和更新之后都會執行,相當於在componentDidMountcomponentDidUpdate兩個生命周期函數中執行回調

如果某些特定值在兩次重渲染之間沒有發生變化,你可以跳過對 effect 的調用,這時候只需要傳入第二個參數,如下:

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // 僅在 count 更改時更新

上述傳入第二個參數后,如果 count 的值是 5,而且我們的組件重渲染的時候 count 還是等於 5,React 將對前一次渲染的 [5] 和后一次渲染的 [5] 進行比較,如果是相等則跳過effects執行

回調函數中可以返回一個清除函數,這是effect可選的清除機制,相當於類組件中componentwillUnmount生命周期函數,可做一些清除副作用的操作,如下:

useEffect(() => {
    function handleStatusChange(status) {
        setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () => {
        ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
});

所以, useEffect相當於componentDidMountcomponentDidUpdate 和 componentWillUnmount 這三個生命周期函數的組合

其它 hooks

在組件通信過程中可以使用useContextrefs學習中我們也用到了useRef獲取DOM結構......

還有很多額外的hooks,如:

  • useReducer
  • useCallback
  • useMemo
  • useRef

三、解決什么

通過對上面的初步認識,可以看到hooks能夠更容易解決狀態相關的重用的問題:

  • 每調用useHook一次都會生成一份獨立的狀態

  • 通過自定義hook能夠更好的封裝我們的功能

編寫hooks為函數式編程,每個功能都包裹在函數中,整體風格更清爽,更優雅

hooks的出現,使函數組件的功能得到了擴充,擁有了類組件相似的功能,在我們日常使用中,使用hooks能夠解決大多數問題,並且還擁有代碼復用機制,因此優先考慮hooks


免責聲明!

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



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