iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 14
0
Modern Web

使用 React 製作簡易專案管理網站:從基礎到實戰系列 第 14

[Day 14] React 保衛戰 - 噓!元件軍隊的內部狀態「state」

  • 分享至 

  • xImage
  •  

讀者進入以下網址:https://codesandbox.io/s/new,就能進到由 CodeSandbox 提供的線上開發環境以及使用 create-react-app 指令建立好的 React 專案來進行練習

「state」- 元件的內部狀態

元件除了可以從父元件取得資料之外,也可以擁有自己內部的資料,就是所謂的 state,也可以稱做是元件的狀態,

我們可以建立多個狀態,每一個狀態都有各自的一個函式來更新狀態,一旦狀態被對應的函式更新,就會觸發擁有該狀態的元件重新執行得以更新畫面。

建立狀態的方式如下:

const [狀態名稱, 更新狀態的函式名稱] = React.useState(狀態的初始值);

以下程式碼為例:

function App() {
  const [number, setNumber] = React.useState(0); 
  
  return (
    <div>
      <p>{number} 個人說讚</p>
      認同請按讚加分享 <button onClick={() => setNumber(number + 1)}>讚</button>
    </div>
  );
}

有效的呼叫更新狀態的函式

呼叫更新狀態的函式不一定會觸發元件重新執行,取決於目前的 state 和新的 state 它們的值。React 使用 ES6 的 Object.is 來判斷目前的 state 和新的 state 是否相等,如果不相等就會觸發元件重新執行,如果相等則不觸發。

useState 的參數

一般情況下,我們呼叫 useState 時會直接傳入 state 的初始值,其實我們也可以傳一個會回傳初始值的函式。

例如以下兩種寫法是等價的:

const [number, setNumber] = React.useState(1 + 2 + 3);
const [number, setNumber] = React.useState(() => 1 + 2 + 3);

「更新狀態的函式」的參數

呼叫「更新狀態的函式」傳入的新的 state 若取決於目前的 state,則我們應該傳入一個會回傳新的 state 的函式,此函式有一個參數為目前的 state,避免產生不如預期的新狀態。

例如以下程式碼:

function App() {
  const [number, setNumber] = React.useState(0);
  
  return (
    <div>
      <p>{number}</p>
      認同請按讚加分享 <button onClick={() => {
        setNumber(number + 1);
        setNumber(number + 1);
        setNumber(number + 1);
      }}>讚</button>
    </div>
  );
}

呼叫三次 setNumber(number + 1) 並不會將原本的 number 加三,一樣只會加一而已。應該改為:

function App() {
  const [number, setNumber] = React.useState(0);
  
  return (
    <div>
      <p>{number}</p>
      認同請按讚加分享 <button onClick={() => {
        setNumber(prevNumber => prevNumber + 1);
        setNumber(prevNumber => prevNumber + 1);
        setNumber(prevNumber => prevNumber + 1);
      }}>讚</button>
    </div>
  );
}

上一篇
[Day 13] React 保衛戰 - 滴答滴答!元件軍隊收到「props」電報
下一篇
[Day 15] React 保衛戰 - 咻!元件與元件透過「context」隔空傳資料
系列文
使用 React 製作簡易專案管理網站:從基礎到實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言