1. 程式人生 > 程式設計 >React hooks的優缺點詳解

React hooks的優缺點詳解

前言

Hook 是 Reacwww.cppcns.comt 16.8 的新增特性。它是完全可選的,並且100%向後相容。它可以讓你使用函式元件的方式,運用類元件以及 react 其他的一些特性,比如管理狀態、生命週期鉤子等。從概念上講,React 元件一直更像是函式。而 Hook 則擁抱了函式,同時也沒有犧牲 React 的精神原則。

優點:

1、程式碼可讀性更強,原本同一塊功能的程式碼邏輯被拆分在了不同的生命週期函式中,容易GEwTkVUdfU使開發者不利於維護和迭代,通過 React Hooks 可以將功能程式碼聚合,方便閱讀維護。例如,每個生命週期中常常會包含一些不相關的邏輯。一般我們都會在 componentDidMount 和 componentDidUpdate 中獲取資料。但是,同一個 componentDidMount 中可能也包含很多其它的邏輯,如設定事件監聽,而之後需在 componentWillUnmount 中清除。相互關聯且需要對照修改的程式碼被進行了拆分,而完全不相關的程式碼卻在同一個方法中組合在一起。如此很容易產生 bug,並且導致邏輯不一致。

2、元件樹層級變淺。在原本的程式碼中,我們經常使用 HOC/render props 等方式來複用元件的狀態,增強功能等,無疑增加了元件樹層數及渲染,在 React DevTools 中觀察過 React 應用,你會發現由 providers,consumers,高階元件,render props 等其他抽象層組成的元件會形成“巢狀地獄”。而在 React Hooks 中,這些功能都可以通過強大的自定義的 Hooks 來實現。
3、不用再去考慮 this 的指向問題。在類元件中,你必須去理解 javascript 中 this 的工作方式。

缺點:

一、響應式的useEffect

寫函式元件時,你不得不改變一些寫法習慣。你必須清楚程式碼中useEffect和useCallback的“依賴項陣列”的改變時機。有時候,你的useEffect依賴某個函式的不可變性,這個函式的不可變性又依賴於另一個函式的不可變性,這樣便形成了一條依賴鏈。一旦這條依賴鏈的某個節點意外地被改變了,你的useEffect就被意外地觸發了,如果你的useEffect是冪等的操作,可能帶來的是效能層次的問題,如果是非冪等,那就糟糕了。

所以,對比componentDidmount和componentDidUpdate,useEffect帶來的心智負擔更大。

二、狀態不同步

函式的執行是獨立的,每個函式都有一份獨立的作用域。函式的變數是儲存在執行時的作用域裡面,當我們有非同步操作的時候,經常會碰到非同步回撥的變數引用是之前的,也就是舊的(這裡也可以理解成閉包)。比如下面的一個例子:

import React,{ useState } from "react";
​
const Counter = () => {
  const [counter,setCounter] = useState(0);
​
  const onAlertButtonClick = () => {
    setTimeout(() => {
      alert("Value: " + counter);
    },3000);
  };
​
  return (
    <div>
      <p>You clicked {counter} times.</p>
      <button onClick={() => setCounter(counter + 1)}>Click me</button>
      <button onClick={onAlertButtonClick}>
        Show me the value in 3 seconds
      </button>
    </div>
  );
};
​
export default Counter;

當你點選Show me the value in 3 seconds的後,緊接著點選Click me使得counte程式設計客棧r的值從0變成1。三秒後,定時器觸發,但alert出來的是0(舊值),但我們希望的結果是當前的狀態1。

這個問題在class component不會出現,因為class component的屬性和方法都存放在一個instance上,呼叫方式是:this.state.xxx和this.method()。因為每次都是從一個不變的instance上進行取值,所以不存在引用是舊的問題。

其實解決這個hooks的問題也可以參照類的instance。用useRef返回的immutable RefObject(current屬性是可變的)來儲存state,然後取值方式從counter變成了: counterRef.current。如下:

import React,{ useState,useRef,useEffect } from "react";
​
const Counter = () => {
  const [counter,setCounter] = useState(0);
  const counterRef = useRef(counter);
​
  const onAlertButtonClick = () => {
    setTimeout(() => {
      alert("Value: " + counterRef.current);
    },3000);
  };
​
  useEffect(() => {
    counterRef.current = counter;
  });
​
  return (
    <div>
      <p>You clicked {counter} times.</p>
      <button onClick={() => setCounter(counter + 1)}>Click me</button>
      <button onClick={onAlertButtonClick}>
        Show me the value in 3 seconds
      </button>
    </div>
  );
};
​
export default Counter;

結果我們所期待,alert的是當前的值1。

怎麼避免react hooks的常見問題

  • 不要在useEffect裡面寫太多的依賴項,劃分這些依賴項成多個單一功能的useEffect。其實這點是遵循了軟體設計的“單一職責模式”。
  • 如果你碰到狀態不同步的問題,可以考慮下手動傳遞引數到函式。如:
   // showCount的countGEwTkVUdfU來自父級作用域 
   const [count,setCount] = useState(xxx); 
   function showCount(){ console.log(count) } 

   // showCount的count來自引數 
   const [count,setCount] = useState(xxx); 
   function showCount(c){ console.log(c) }

但這個也只能解決一部分問題,很多時候你不得不使用上述的useRef方案。

3. 重視eslint-plugin-react-hooks外掛的警告。

4. 複雜業務的時候,使用CoGEwTkVUdfUmponent代替hooks。

以上就是React hooks的優缺點詳解的詳細內容,更多關於React hooks的優缺點的資料請關注我們其它相關文章!