博客 / 詳情

返回

精讀React hooks(一):useState 的幾個基礎用法和進階技巧

🎯 【專欄:精讀React Hooks】我用16篇文章詳細解讀16個React官方的Hook,每一篇都盡力做到比官方文檔更仔細且更易讀,同時提供了開源demo作為演示。如果你是新手,可以把這個專欄當作學習材料,如果你有一定經驗了,可以把這份專欄當作查缺補漏的資料。
專欄首發地址:J實驗室 - React Hooks
專欄演示地址:React Hooks Demo
加入「前端&全棧交流羣」

自從 React v16.8 版本以來,React Hooks 為我們提供了全新的編寫和思考 React 組件的方式。不僅管理狀態和生命週期變得更簡潔、更強大,Hooks 還引入了併發渲染和其他高級功能。本系列文章將詳細探討每一個 Hook,從基礎到高級。首篇,我們將探討最常用的 hook——useState

useState 的基本用法

useState主要用於給組件添加狀態變量。注意,我們只能在組件的頂層或自定義的 Hooks 中調用useState

初始化狀態

基礎定義

const [age, setAge] = useState(42);

懶初始化

對於需要計算得到的初始狀態,可以使用函數傳遞給useState。這樣,函數只在初次渲染時執行,而非每次渲染。

const [todos, setTodos] = useState(createInitialTodos); // 注意:傳遞函數本身,非執行結果

更新狀態

直接更新vs函數式更新

大部分情況,直接更新狀態即可:

setAge(newState);

但當新狀態依賴於前一個狀態時,推薦使用函數式更新。這確保了更新準確性,特別是在併發模式下。

setState(prevState => prevState + 1);

以下兩個例子展示函數式更新的重要性:

// 示例1: 使用函數式更新
import { useState } from 'react';

export default function Counter() {
  const [age, setAge] = useState(42);

  function increment() {
    setAge(a => a + 1); // 函數式更新
  }

  return (
    <>
      <h1>Your age: {age}</h1>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
    </>
  );
}
// 結果:點擊 +3 時,age 更新為 45。
// 示例2: 使用直接更新
import { useState } from 'react';

export default function Counter() {
  const [age, setAge] = useState(42);
  function increment() {
    setAge(age + 1); // 直接更新
  }
  return (
    <>
      <h1>Your age: {age}</h1>
      <button onClick={() => {
        increment();
        increment();
        increment();
      }}>+3</button>
    </>
  );
}
// 結果:點擊 +3 時,可能只更新為 43。

對象與數組的更新

對象和數組的更新需要創建新的引用,而不是直接修改原狀態。

setForm({
  ...form,
  name: e.target.value // 更新這個屬性
});

// 錯誤示例:
// form.name = e.target.value
setTodos([
  ...todos,
  {
    id: nextId++,
    title: title,
    done: false
  }
]);

// 錯誤示例
// todos.push({
//   id: nextId++,
//   title: title,
//   done: false
// });
// setTodos(todos);

函數的更新

把函數存儲到state裏是很少見的做法,但某些情況下,我們有可能需要這麼做。

先看一個錯誤的示例:

const [fn, setFn] = useState(someFunction);

function handleClick() {
  setFn(someOtherFunction);
}

根據上文,我們知道這樣的用法是把函數的返回值存儲或更新到狀態中,並不是把函數存儲到狀態中。

如果你想在狀態中存儲一個函數,你需要使用一個箭頭函數來“包裹”它。這是正確的做法:

const [fn, setFn] = useState(() => someFunction);

function handleClick() {
  setFn(() => someOtherFunction);
}

那麼我們什麼時候會需要這樣使用?這裏介紹一些可能的場景:

  1. 可配置的行為: 你可能有一個組件,它的行為可以由父組件進行配置。在這種情況下,你可以將函數作為狀態存儲,以便在組件的生命週期中更改或更新它。
  2. 動態創建的函數: 在某些情況下,你可能需要基於組件的某些屬性或狀態動態創建函數。將這些函數存儲為狀態可以確保你只在必要時重新創建它們。
  3. 回調和外部交互: 如果你的組件與外部系統交互,並且需要提供回調函數,你可能希望在狀態中存儲這些回調函數,以便在適當的時候更改或更新它們。
  4. 延遲執行的函數: 在某些情況下,你可能想要在將來的某個時間點執行函數(例如,使用setTimeout)。將函數存儲為狀態可以確保即使組件的其他部分發生變化,你也可以訪問到最初的函數引用。
  5. 與第三方庫的集成: 有些第三方庫可能要求你提供並在後續更改函數。在這種情況下,將函數作為狀態存儲可能會更加方便。

結語

在這篇文章中,我們深入探討了 React 的useStateHook,從它的基礎用法到一些進階技巧。掌握好useState是走向 React 高手之路的關鍵一步。在未來的文章中,我們還將繼續探討其他的 Hooks。

專欄資源

專欄首發地址:👉 精讀React Hooks
專欄演示地址:👉 React Hooks Demos
進羣交流:👉加入「前端&Node交流羣」

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.