首頁 > 軟體

React Hook之使用State Hook的方法

2022-03-16 13:00:13

Hook 簡介章節中使用下面的例子介紹了 Hook:

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

我們將通過將這段程式碼與一個等價的 class 範例進行比較來開始學習 Hook。

等價的 class 範例

如果你之前在 React 中使用過 class,這段程式碼看起來應該很熟悉:

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 初始值為 { count: 0 } ,當用戶點選按鈕後,我們通過呼叫 this.setState() 來增加 state.count。整個章節中都將使用該 class 的程式碼片段做範例。

Hook 和函陣列件

複習一下, React 的函陣列件是這樣的:

const Example = (props) => {
  // 你可以在這使用 Hook
  return <div />;
}

或是這樣:

function Example(props) {
  // 你可以在這使用 Hook
  return <div />;
}

你之前可能把它們叫做“無狀態元件”。但現在我們為它們引入了使用 React state 的能力,所以我們更喜歡叫它”函陣列件”。

Hook 在 class 內部是不起作用的。但你可以使用它們來取代 class 。

Hook 是什麼?

在新範例中,首先引入 React 中 useState 的 Hook

import React, { useState } from 'react';
function Example() {
  // ...
}
  • Hook 是什麼? Hook 是一個特殊的函數,它可以讓你“鉤入” React 的特性。例如,useState 是允許你在 React 函陣列件中新增 state 的 Hook。稍後我們將學習其他 Hook。
  • 什麼時候我會用 Hook? 如果你在編寫函陣列件並意識到需要向其新增一些 state,以前的做法是必須將其轉化為 class。現在你可以在現有的函陣列件中使用 Hook。

宣告 State 變數

在 class 中,我們通過在建構函式中設定 this.state 為 { count: 0 } 來初始化 count state 為 0

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

在函陣列件中,我們沒有 this,所以我們不能分配或讀取 this.state。我們直接在元件中呼叫 useState Hook:

import React, { useState } from 'react';
function Example() {
  // 宣告一個叫 「count」 的 state 變數
  const [count, setCount] = useState(0);
  • 呼叫 useState 方法的時候做了什麼? 它定義一個 “state 變數”。我們的變數叫 count, 但是我們可以叫他任何名字,比如 banana。這是一種在函數呼叫時儲存變數的方式 —— useState 是一種新方法,它與 class 裡面的 this.state 提供的功能完全相同。一般來說,在函數退出後變數就會”消失”,而 state 中的變數會被 React 保留。
  • useState 需要哪些引數? useState() 方法裡面唯一的引數就是初始 state。不同於 class 的是,我們可以按照需要使用數位或字串對其進行賦值,而不一定是物件。在範例中,只需使用數位來記錄使用者點選次數,所以我們傳了 0 作為變數的初始 state。(如果我們想要在 state 中儲存兩個不同的變數,只需呼叫 useState() 兩次即可。)
  • useState 方法的返回值是什麼? 返回值為:當前 state 以及更新 state 的函數。這就是我們寫 const [count, setCount] = useState() 的原因。這與 class 裡面 this.state.count 和 this.setState 類似,唯一區別就是你需要成對的獲取它們。如果你不熟悉我們使用的語法,我們會在本章節的底部介紹它。

既然我們知道了 useState 的作用,我們的範例應該更容易理解了:

import React, { useState } from 'react';
function Example() {
  // 宣告一個叫 "count" 的 state 變數
  const [count, setCount] = useState(0);

我們宣告了一個叫 count 的 state 變數,然後把它設為 0。React 會在重複渲染時記住它當前的值,並且提供最新的值給我們的函數。我們可以通過呼叫 setCount 來更新當前的 count

注意

你可能想知道:為什麼叫 useState 而不叫 createState?

“Create” 可能不是很準確,因為 state 只在元件首次渲染的時候被建立。在下一次重新渲染時,useState 返回給我們當前的 state。否則它就不是 state 了!這也是 Hook 的名字總是以 use 開頭的一個原因。我們將在後面的 Hook 規則中瞭解原因。

讀取 State

當我們想在 class 中顯示當前的 count,我們讀取 this.state.count

  <p>You clicked {this.state.count} times</p>

在函數中,我們可以直接用 count:

  <p>You clicked {count} times</p>

更新 State

在 class 中,我們需要呼叫 this.setState() 來更新 count 值:

 <button onClick={() => this.setState({ count: this.state.count + 1 })}>
    Click me
  </button>

在函數中,我們已經有了 setCount 和 count 變數,所以我們不需要 this:

  <button onClick={() => setCount(count + 1)}>
    Click me
  </button>

小結

現在讓我們來仔細回顧一下學到的知識,看下我們是否真正理解了。

import React, { useState } from 'react';
function Example() {
	const [count, setCount] = useState(0);
	return (
      <div>
        <p>You clicked {count} times</p>
        <button onClick={() => setCount(count + 1)}>
         Click me
        </button>
      </div>
   );
}
  • 第一行 - 引入React 中的 useState Hook。它讓我們在函陣列件中儲存內部 state
  • 第四行 - 在 Example 元件內部,我們通過呼叫 useState Hook 宣告了一個新的 state 變數。它返回一對值給到我們命名的變數上。我們把變數命名為 count,因為它儲存的是點選次數。我們通過傳 0 作為 useState 唯一的引數來將其初始化為 0。第二個返回的值本身就是一個函數。它讓我們可以更新 count 的值,所以我們叫它 setCount
  • 第九行 - 當用戶點選按鈕後,我們傳遞一個新的值給 setCount。React 會重新渲染 Example 元件,並把最新的 count 傳給它。

提示:方括號有什麼用?

你可能注意到我們用方括號定義了一個 state 變數

const [count, setCount] = useState(0);

等號左邊名字並不是 React API 的部分,你可以自己取名字:

const [fruit, setFruit] = useState('banana');

這種 JavaScript 語法叫陣列解構。它意味著我們同時建立了 fruit 和 setFruit 兩個變數,fruit 的值為 useState 返回的第一個值,setFruit 是返回的第二個值。它等價於下面的程式碼:

  var fruitStateVariable = useState('banana'); // 返回一個有兩個元素的陣列
  var fruit = fruitStateVariable[0]; // 陣列裡的第一個值
  var setFruit = fruitStateVariable[1]; // 陣列裡的第二個值

當我們使用 useState 定義 state 變數時候,它返回一個有兩個值的陣列。第一個值是當前的 state,第二個值是更新 state 的函數。使用 [0] 和 [1] 來存取有點令人困惑,因為它們有特定的含義。這就是我們使用陣列解構的原因。

提示:使用多個 state 變數

將 state 變數宣告為一對 [something, setSomething] 也很方便,因為如果我們想使用多個 state 變數,它允許我們給不同的 state 變數取不同的名稱:

function ExampleWithManyStates() {
  // 宣告多個 state 變數
  const [age, setAge] = useState(42);
  const [fruit, setFruit] = useState('banana');
  const [todos, setTodos] = useState([{ text: '學習 Hook' }]);

在以上元件中,我們有區域性變數 agefruit 和 todos,並且我們可以單獨更新它們:

  function handleOrangeClick() {
    // 和 this.setState({ fruit: 'orange' }) 類似
    setFruit('orange');
  }

不必使用多個 state 變數。State 變數可以很好地儲存物件和陣列,因此,你仍然可以將相關資料分為一組。然而,不像 class 中的 this.setState,更新 state 變數總是替換它而不是合併它。

總結

本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容! 


IT145.com E-mail:sddin#qq.com