iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0

今天要來學習state的應用,內容包含:

  • 認識state
  • 操作方法
  • stateHook

什麼是state? 如何理解

state,字面上的意思就是當前的程式狀態,我們也可以試著用生活中的例子來理解,譬如我們買了一杯咖啡,咖啡是「熱的」,「熱的」就是一種state,假設過了一小時咖啡冷了,「冷的」也會是一種state,而在「熱的」和「冷的」之間也存在著許多其他的state(漸漸變冷的狀態間),而在程式中,state是由行的程式操作和反映的數據。

為什麼我們需要state?

import { sculptureList } from './data.js';

export default function Gallery() {
  let index = 0;

  function handleClick() {
    index = index + 1;
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i>
        by {sculpture.artist}
      </h2>
      <h3>
        ({index + 1} of {sculptureList.length})
      </h3>
      <img
        src={sculpture.url}
        alt={sculpture.alt}
      />
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

這是一個Gallery 的元件,當中含有處理「下一張」的按鈕,透過起始值設定為0,並試圖用 index = index + 1;來達到跳轉到下一張的功能。但這個並沒有辦法運作,原因是因為

  1. 本地變數沒辦法在渲染間儲存資料:

React 元件中定義的變數,通常用於在渲染過程中儲存或處理數據。這些變數僅在函數的執行期間存在,並且在每次組件重新渲染時都會重新創建。因此,它們不會在不同渲染之間保留任何狀態。

  1. 本地變數的更改不會觸發重新渲染

React 不會自動監聽本地變數的更改並觸發元件的重新渲染。這意味著,即使在渲染函數中修改了本地變數的值,React 也不會意識到這些更改,並不會導致元件再次渲染。(底下補充:React的渲染機制)

好的,所以我們要解決的事情有二:儲存資料以及觸發渲染,而在React當中我們可以透過useState 來處理這些事情。

操作方法

我們可以透過以下的三個步驟來使用useState

  1. import
import { useState } from 'react';
  1. 在function內創建狀態變數
const [index, setIndex] = useState(0);

這是解構賦值的應用。

在這邊我們創建了名為index的狀態變數,並設定起始值為0

  1. 使用狀態變數
function handleClick() {
  setIndex(index + 1);
}

如同下面的結果:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);

  function handleClick() {
    setIndex(index + 1);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i>
        by {sculpture.artist}
      </h2>
      <h3>
        ({index + 1} of {sculptureList.length})
      </h3>
      <img
        src={sculpture.url}
        alt={sculpture.alt}
      />
      <p>
        {sculpture.description}
      </p>
    </>
  );
}

這樣子「next」按鈕就可以正常運作了。

另一種方法

這邊我們使用的是import,我們也可以使用另一種不使用import的方法來編寫

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

這樣子的寫法則不需要使用import,二種方法也是相等的。

Hook?

我們剛剛使用的useState也可以說是React hook的一種,在React當中以‘’use’’開頭的function稱為Hook,Hook是一種特殊的function,它只在渲染當中運作,而且它只能在元件中的最高層級被呼叫,沒辦法在loops或是巢狀的function當中使用,使用 useStateuseEffect 或其他 Hooks 時,它們應該始終存在於組件中,而不受條件語句或其他邏輯的影響。關於Hook後續的文章會再更詳細介紹。

再細看stateHook

useState Hook當中有什麼呢?

useStateHook回傳的array有二個東西。

  1. 狀態變數當中保存著當前的值
  2. 狀態setter function 能夠更新並觸發下一個渲染

而這二者的命名其實不限,就算使用

const [hello, world] = React.useState(0);

這樣其實也是能運作的,但命名上約定成俗的命名概念是

const [something, setSomething]

再次注意,useState接受的是一個參數,也就是初始值。

使用複數個狀態變數

我們也可以視情況所需同時運用一個以上的狀態變數:

import { useState } from 'react';
import { sculptureList } from './data.js';

export default function Gallery() {
  const [index, setIndex] = useState(0);
  const [showMore, setShowMore] = useState(false);

  //第一個處理「下一張」的點擊按鈕funciton:+1
  function handleNextClick() {
    setIndex(index + 1);
  }
  //第二個處理「顯示更多資訊」的點擊按鈕function:布林值
  function handleMoreClick() {
    setShowMore(!showMore);
  }

  let sculpture = sculptureList[index];
  return (
    <>
      <button onClick={handleNextClick}>
        Next
      </button>
      <h2>
        <i>{sculpture.name} </i>
        by {sculpture.artist}
      </h2>
      <h3>
        ({index + 1} of {sculptureList.length})
      </h3>
      <button onClick={handleMoreClick}>
        {showMore ? 'Hide' : 'Show'} details
      </button>
      {showMore && <p>{sculpture.description}</p>}
      <img
        src={sculpture.url}
        alt={sculpture.alt}
      />
    </>
  );
}

當二個狀態彼此的關係不相關,可以透過複數個狀態變數來控制,然而當狀態彼此之間有其關連性經常連動性調整時,應該將其合而為一。

其他注意事項

state是獨立且私有的(isolated and private),也就是說當你渲染了同一個元件二次,二者會有完全獨立的state,就算更動其中之一,也不會影響另一方。

補充

React 的渲染機制:當 React 重新渲染一個元件時,它會將該元件的整個渲染函數重新執行一次,然後將新生成的 JSX 與之前的版本進行比較,以確定需要更新的部分。

參考資料


上一篇
Day 12 - 在React 處理事件(下)
下一篇
Day 14 - React 的渲染機制以及 state 的過程
系列文
30 days of React 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言