React教程:4 個 useState Hook 示例

摘要: React示例教程。

到 React 16.8 目前爲止,如果編寫函數組件,然後遇到需要添加狀態的情況,咱們就必須將組件轉換爲類組件。

編寫 class Thing extends React.Component,將函數體複製到render()方法中,修復縮進,最後添加需要的狀態。

今天,可以使用 Hook 獲得相同的功能,併爲自己節省了工作時間。在本文中,主要介紹useState hook。

useState 做啥子的

useState hook 允許咱們向函數組件添加狀態,我們通常稱這些爲“ hooks”,但它們實際上是函數,與 React 16.8 捆綁在一起。 通過在函數組件中調用useState,就會創建一個單獨的狀態。

在類組件中,state 總是一個對象,可以在該對象上添加保存屬性。

對於 hooks,state 不必是對象,它可以是你想要的任何類型-數組、數字、布爾值、字符串等等。每次調用useState都會創建一個state塊,其中包含一個值。

示例1:使用 useState 顯示/隱藏組件

這個示例是一個組件,它顯示一些文本,並在末尾顯示一個read more鏈接,當單擊鏈接時,它展開剩下的文本。

    import React, { useState } from 'react';
    import ReactDOM from 'react-dom';
    
    // 兩個 props:
    //   text - 顯示的內容
    //   maxLength - 在點擊“read more”之前顯示多少個字符
    function LessText({ text, maxLength }) {
      // 創建一個狀態,並將其初始化爲“true”
      const [hidden, setHidden] = useState(true);
    

      if (text <= maxLength) {
        return <span>{text}</span>;
      }
    
      return (
        <span>
          {hidden ? `${text.substr(0, maxLength).trim()} ...` : text}
          {hidden ? (
            <a onClick={() => setHidden(false)}> read more</a>
          ) : (
            <a onClick={() => setHidden(true)}> read less</a>
          )}
        </span>
      );
    }
    
    ReactDOM.render(
      <LessText
        text={`專注、努力是成功的真正關鍵。把你的眼睛盯在目標上,然後朝着目標邁出下一步`}
        maxLength={35}
      />,
      document.querySelector('#root')
    );

僅用一行代碼,我們就使這個函數組件有狀態:

    const [hidden, setHidden] = useState(true);

但是這個函數到底在做什麼呢?如果每次渲染都調用它(確實如此),它又是如何保留狀態的。

Hooks 實現的技巧

這裏的“神奇”之處是,React在每個組件的幕後維護一個對象,並且在這個持久對象中,有一個“狀態單元”數組。當你調用useState時,React將該狀態存儲在下一個可用的單元格中,並遞增數組索引。

假設你的 hooks 總是以相同的順序調用(如果遵循 hooks 的規則,它們將是相同的順序),React能夠查找特定useState調用的前一個值。對useState的第一個調用存儲在第一個數組元素中,第二個調用存儲在第二個元素中,依此類推。

這也不是很神奇的事情,主要它依賴於你可能沒有想過的事實:咱們寫的的組件是由React調用 ,所以它可以在調用組件之前事先做好一些工作。 而且,渲染組件的行爲不僅僅是函數調用。 像<Thing />這樣的JSX被編譯爲React.createElement(Thing) - 顯然 React 可以控制它的調用方式和時間。

示例2:根據之前的狀態更新狀態

看看另一個例子:根據前一個值更新state的值。

咱們要造個計步器,每點擊一次按鈕,就計一次,點擊完後,它會告訴你你走了多少步。

    import React, { useState } from 'react';
    
    function StepTracker() {
      const [steps, setSteps] = useState(0);
    
      function increment() {
        setSteps(steps => steps + 1);
      }
    
      return (
        <div>
          總共走了 {steps} 步!
          <br />
          <button onClick={increment}>
            點點我,步數不是個事!
          </button>
        </div>
      );
    }
    
    ReactDOM.render(
      <StepTracker />,
      document.querySelector('#root')
    );

首先,通過調用useState創建一個新的state,並將其初始化爲0。它返回steps的當前值0setSteps函數來更新 steps,用 increment函數來對steps進行增 1 操作。

這裏還可以優化的提取increment函數,可以直接將 increment 函數裏面的內聯到 onClick 裏面:

    <button onClick={() => setSteps(steps => steps + 1)}>
      I took another step
    </button>

示例3: state 作爲數組

記住,state可以保存任何你想要的值。下面是一個隨機數列表的例子,單擊按鈕將向列表添加一個新的隨機數:

    function RandomList() {
      const [items, setItems] = useState([]);
    
      const addItem = () => {
        setItems([
          ...items,
          {
            id: items.length,
            value: Math.random() * 100
          }
        ]);
      };
    
      return (
        <>
          <button onClick={addItem}>Add a number</button>
          <ul>
            {items.map(item => (
              <li key={item.id}>{item.value}</li>
            ))}
          </ul>
        </>
      );
    }

注意,我們state初始化爲空數組[],並在addItem函數中更新值。

setItems 更新 state 不會將舊值“合併” - 它會使用新值覆蓋state。 這與this.setState在類中的工作方式不同。

示例4:具有多個鍵的 state

再來看看,state爲對象的例子,創建一個包含2個字段的登錄表單:usernamepassword

下面示例主要展示如何在一個state對象中存儲多個值,以及如何更新單個值。

    function LoginForm() {
      const [form, setValues] = useState({
        username: '',
        password: ''
      });
    
      const printValues = e => {
        e.preventDefault();
        console.log(form.username, form.password);
      };
    
      const updateField = e => {
        setValues({
          ...form,
          [e.target.name]: e.target.value
        });
      };
    
      return (
        <form onSubmit={printValues}>
          <label>
            Username:
            <input
              value={form.username}
              name="username"
              onChange={updateField}
            />
          </label>
          <br />
          <label>
            Password:
            <input
              value={form.password}
              name="password"
              type="password"
              onChange={updateField}
            />
          </label>
          <br />
          <button>Submit</button>
        </form>
      );
    }

如果想試試,可查看 CodeSandbox

首先,我們創建一個state片段,並用一個對象初始化它

    const [form, setValues] = useState({
      username: '',
      password: ''
    })

這看起來像是在類中初始化狀態的方式。

還有一個處理提交的函數,其中,e.preventDefault來阻止頁面刷新並打印出表單值。

updateField函數更有意思。它使用setValues傳遞一個對象,爲了確保現有的狀態不被覆蓋,這裏使用了展開運算(...form)。

代碼部署後可能存在的BUG沒法實時知道,事後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug

原文:https://daveceddia.com/usestate-hook-examples/

關於Fundebug

Fundebug專注於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了20億+錯誤事件,付費客戶有陽光保險、核桃編程、荔枝FM、掌門1對1、微脈、青團社等衆多品牌企業。歡迎大家免費試用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章