React教程:4 個 useState Hook 示例

摘要: React示例教程莹规。

到 React 16.8 目前為止请梢,如果編寫函數(shù)組件正歼,然后遇到需要添加狀態(tài)的情況辐马,咱們就必須將組件轉(zhuǎn)換為類組件。

編寫 class Thing extends React.Component局义,將函數(shù)體復制到render()方法中喜爷,修復縮進,最后添加需要的狀態(tài)旭咽。

今天贞奋,可以使用 Hook 獲得相同的功能,并為自己節(jié)省了工作時間穷绵。在本文中轿塔,主要介紹useState hook。

useState 做啥子的

useState hook 允許咱們向函數(shù)組件添加狀態(tài)仲墨,我們通常稱這些為“ hooks”勾缭,但它們實際上是函數(shù),與 React 16.8 捆綁在一起目养。 通過在函數(shù)組件中調(diào)用useState俩由,就會創(chuàng)建一個單獨的狀態(tài)。

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

對于 hooks努释,state 不必是對象碘梢,它可以是你想要的任何類型-數(shù)組、數(shù)字伐蒂、布爾值煞躬、字符串等等。每次調(diào)用useState都會創(chuàng)建一個state塊逸邦,其中包含一個值恩沛。

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

這個示例是一個組件,它顯示一些文本缕减,并在末尾顯示一個read more鏈接雷客,當單擊鏈接時,它展開剩下的文本桥狡。

    import React, { useState } from 'react';
    import ReactDOM from 'react-dom';
    
    // 兩個 props:
    //   text - 顯示的內(nèi)容
    //   maxLength - 在點擊“read more”之前顯示多少個字符
    function LessText({ text, maxLength }) {
      // 創(chuàng)建一個狀態(tài)佛纫,并將其初始化為“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={`專注妓局、努力是成功的真正關(guān)鍵总放。把你的眼睛盯在目標上呈宇,然后朝著目標邁出下一步`}
        maxLength={35}
      />,
      document.querySelector('#root')
    );

僅用一行代碼,我們就使這個函數(shù)組件有狀態(tài):

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

但是這個函數(shù)到底在做什么呢?如果每次渲染都調(diào)用它(確實如此)局雄,它又是如何保留狀態(tài)的甥啄。

Hooks 實現(xiàn)的技巧

這里的“神奇”之處是,React在每個組件的幕后維護一個對象炬搭,并且在這個持久對象中蜈漓,有一個“狀態(tài)單元”數(shù)組。當你調(diào)用useState時宫盔,React將該狀態(tài)存儲在下一個可用的單元格中融虽,并遞增數(shù)組索引。

假設你的 hooks 總是以相同的順序調(diào)用(如果遵循 hooks 的規(guī)則灼芭,它們將是相同的順序)有额,React能夠查找特定useState調(diào)用的前一個值。對useState的第一個調(diào)用存儲在第一個數(shù)組元素中彼绷,第二個調(diào)用存儲在第二個元素中巍佑,依此類推。

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

示例2:根據(jù)之前的狀態(tài)更新狀態(tài)

看看另一個例子:根據(jù)前一個值更新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}>
            點點我邦危,步數(shù)不是個事洋侨!
          </button>
        </div>
      );
    }
    
    ReactDOM.render(
      <StepTracker />,
      document.querySelector('#root')
    );

首先,通過調(diào)用useState創(chuàng)建一個新的state倦蚪,并將其初始化為0希坚。它返回steps的當前值0setSteps函數(shù)來更新 steps,用 increment函數(shù)來對steps進行增 1 操作陵且。

這里還可以優(yōu)化的提取increment函數(shù)裁僧,可以直接將 increment 函數(shù)里面的內(nèi)聯(lián)到 onClick 里面:

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

示例3: state 作為數(shù)組

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

    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初始化為空數(shù)組[],并在addItem函數(shù)中更新值获洲。

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

示例4:具有多個鍵的 state

再來看看贡珊,state為對象的例子最爬,創(chuàng)建一個包含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寒随。

首先糠悯,我們創(chuàng)建一個state片段,并用一個對象初始化它

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

這看起來像是在類中初始化狀態(tài)的方式牢裳。

還有一個處理提交的函數(shù)逢防,其中,e.preventDefault來阻止頁面刷新并打印出表單值蒲讯。

updateField函數(shù)更有意思忘朝。它使用setValues傳遞一個對象,為了確迸邪铮現(xiàn)有的狀態(tài)不被覆蓋局嘁,這里使用了展開運算(...form)。

代碼部署后可能存在的BUG沒法實時知道晦墙,事后為了解決這些BUG悦昵,花了大量的時間進行l(wèi)og 調(diào)試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具 Fundebug晌畅。

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

關(guān)于Fundebug

Fundebug專注于JavaScript但指、微信小程序、微信小游戲抗楔、支付寶小程序棋凳、React Native、Node.js和Java線上應用實時BUG監(jiān)控连躏。 自從2016年雙十一正式上線剩岳,F(xiàn)undebug累計處理了20億+錯誤事件,付費客戶有陽光保險入热、核桃編程拍棕、荔枝FM晓铆、掌門1對1、微脈绰播、青團社等眾多品牌企業(yè)骄噪。歡迎大家免費試用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末幅垮,一起剝皮案震驚了整個濱河市腰池,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌忙芒,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讳侨,死亡現(xiàn)場離奇詭異呵萨,居然都是意外死亡,警方通過查閱死者的電腦和手機跨跨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門潮峦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人勇婴,你說我怎么就攤上這事忱嘹。” “怎么了耕渴?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵拘悦,是天一觀的道長。 經(jīng)常有香客問我橱脸,道長础米,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任添诉,我火速辦了婚禮屁桑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘栏赴。我一直安慰自己蘑斧,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布须眷。 她就那樣靜靜地躺著竖瘾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪柒爸。 梳的紋絲不亂的頭發(fā)上准浴,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音捎稚,去河邊找鬼乐横。 笑死求橄,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的葡公。 我是一名探鬼主播罐农,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼催什!你這毒婦竟也來了涵亏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蒲凶,失蹤者是張志新(化名)和其女友劉穎气筋,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旋圆,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡宠默,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了灵巧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搀矫。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖刻肄,靈堂內(nèi)的尸體忽然破棺而出瓤球,到底是詐尸還是另有隱情,我是刑警寧澤敏弃,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布卦羡,位于F島的核電站,受9級特大地震影響权她,放射性物質(zhì)發(fā)生泄漏虹茶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一隅要、第九天 我趴在偏房一處隱蔽的房頂上張望蝴罪。 院中可真熱鬧,春花似錦步清、人聲如沸要门。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽欢搜。三九已至,卻和暖如春谴轮,著一層夾襖步出監(jiān)牢的瞬間炒瘟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工第步, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留疮装,地道東北人缘琅。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像廓推,于是被迫代替她去往敵國和親刷袍。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容