03. 該嘗嘗React Hook了。初體驗

Hook

Hook 是 React 16.8.0 的新增特性癣防。

Hook 使你在非 class 的情況下可以使用更多的 React 特性。Hook 不能在 class 組件中使用芯咧。

使用規(guī)則:

  • 只能在函數(shù)最外層調(diào)用 Hook。不要在循環(huán)、條件判斷或者子函數(shù)中調(diào)用唬党。
  • 只能在 React 的函數(shù)組件中調(diào)用 Hook。不要在其他 JavaScript 函數(shù)中調(diào)用鬼佣。

State Hook

useState

使用useState可以不通過class組件而在函數(shù)組件內(nèi)使用state驶拱,可通過多次調(diào)用聲明多個state

  • 參數(shù):

    useState() 方法里面唯一的參數(shù)就是初始 state。

  • 返回值:

    當(dāng)前 state 以及更新 state 的函數(shù)晶衷。

函數(shù)式更新:

如果新的 state 需要通過使用先前的 state 計算得出蓝纲,那么可以將函數(shù)傳遞給 setState。該函數(shù)將接收先前的 state晌纫,并返回一個更新后的值税迷。

function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}
      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
    </>
  );
}

Effect Hook

Effect Hook 可以讓你在函數(shù)組件中執(zhí)行副作用操作(在 React 組件中執(zhí)行過數(shù)據(jù)獲取、訂閱或者手動修改過 DOM锹漱。我們統(tǒng)一把這些操作稱為“副作用”箭养,或者簡稱為“作用”。)

useEffect

可以把 useEffect Hook 看做 componentDidMount哥牍,componentDidUpdate 和 componentWillUnmount 這三個函數(shù)的組合毕泌。

useEffect 會在每次渲染后(第一次渲染之后和每次更新之后)都執(zhí)行,如果你的 effect 返回一個函數(shù)嗅辣,React 將會在組件卸載的時候執(zhí)行清除操作時調(diào)用它撼泛。

useEffect在組件內(nèi)可多次調(diào)用,Hook 允許我們按照代碼的用途分離他們澡谭,React 將按照 effect 聲明的順序依次調(diào)用組件中的每一個 effect愿题。

使用位置:

組件內(nèi)部調(diào)用 useEffect。 將 useEffect 放在組件內(nèi)部讓我們可以在 effect 中直接訪問 count state 變量(或其他 props)蛙奖。

性能優(yōu)化:

useEffect 的第二個可選參數(shù)可以實現(xiàn)如果某些特定值在兩次重渲染之間沒有發(fā)生變化潘酗,你可以通知 React 跳過對 effect 的調(diào)用。請確保數(shù)組中包含了所有外部作用域中會隨時間變化并且在 effect 中使用的變量

// 僅在 count 更改時更新
useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); 

示例代碼詳解 useStateuseEffect

// 引入 React 中的 useState Hook外永。它讓我們在函數(shù)組件中存儲內(nèi)部 state
// 引入 useEffect
import React, { useState, useEffect } from 'react';

function Example(props) {
  // 聲明了一個叫 count 的 state 變量崎脉,然后把它設(shè)為 0
  const [count, setCount] = useState(0);
  // 聲明第2個state
  const [isOnline, setIsOnline] = useState(null);

  // 無需清除的 effect
  useEffect(() => {
    // 將 document 的 title 設(shè)置為包含了點擊次數(shù)的消息。
    document.title = `You clicked ${count} times`;
  });
  
  // 需要清除的 effect
  useEffect(() => {
    function handleFn(val) {
      setIsOnline(val);
    }
    // 注冊監(jiān)聽
    XXAPI.subscribe(handleFn);
    // 清除監(jiān)聽
    return () => {
      XXAPI.unsubscribe(handleFn);
    };
  });

  return (
    <div>
      // 讀取 State: 我們可以直接用 count
      <p>You clicked {count} times</p>
      // 更新 State: 可以通過調(diào)用 setCount 來更新當(dāng)前的 count
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

useLayoutEffect

其函數(shù)簽名與 useEffect 相同伯顶,但它會在所有的 DOM 變更之后同步調(diào)用 effect囚灼。可以使用它來讀取 DOM 布局并同步觸發(fā)重渲染祭衩。在瀏覽器執(zhí)行繪制之前灶体,useLayoutEffect 內(nèi)部的更新計劃將被同步刷新。盡可能使用標(biāo)準(zhǔn)的 useEffect 以避免阻塞視覺更新掐暮。

與 componentDidMount 或 componentDidUpdate 不同蝎抽,使用 useEffect 調(diào)度的 effect 不會阻塞瀏覽器更新屏幕,這讓你的應(yīng)用看起來響應(yīng)更快。大多數(shù)情況下樟结,effect 不需要同步地執(zhí)行养交。在個別情況下(例如測量布局),這時需要用到useLayoutEffect

useRef

useRef 返回一個可變的 ref 對象瓢宦,其 .current 屬性被初始化為傳入的參數(shù)(initialValue)碎连。返回的 ref 對象在組件的整個生命周期內(nèi)保持不變。

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` 指向已掛載到 DOM 上的文本輸入元素
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

useRef() 比 ref 屬性更有用驮履。它可以很方便地保存任何可變值鱼辙,其類似于在 class 中使用實例字段的方式。當(dāng) ref 對象內(nèi)容發(fā)生變化時玫镐,useRef 并不會通知你倒戏。變更 .current 屬性不會引發(fā)組件重新渲染。

自定義Hook

自定義Hook 是一個函數(shù)恐似,其名稱以 use 開頭(必須以 use 開頭)杜跷,函數(shù)內(nèi)部可以調(diào)用其他的 Hook。自定義Hook用于提取多組件之間的共享邏輯蹂喻,可用于替代 render propsHOC葱椭。

在需要共享邏輯的組件內(nèi)調(diào)用很簡單,只需要引入定義好的自定義Hook口四,并傳入自己想要的參數(shù)拿到你想要的返回值作用于當(dāng)前組件孵运。

如下例:
  1. 提取自定義Hook:
import React, { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}
  1. 使用自定義Hook:
function FriendListItem(props) {
  const isOnline = useFriendStatus(props.friend.id);

  return (
    <li style={{ color: isOnline ? 'green' : 'black' }}>
      {props.friend.name}
    </li>
  );
}

原文git地址 覺得有用的話,來個star鼓勵蔓彩,持續(xù)更新中治笨。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市赤嚼,隨后出現(xiàn)的幾起案子旷赖,更是在濱河造成了極大的恐慌,老刑警劉巖更卒,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件等孵,死亡現(xiàn)場離奇詭異,居然都是意外死亡蹂空,警方通過查閱死者的電腦和手機俯萌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來上枕,“玉大人咐熙,你說我怎么就攤上這事”嫫迹” “怎么了棋恼?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我爪飘,道長义起,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任师崎,我火速辦了婚禮并扇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘抡诞。我一直安慰自己,他們只是感情好土陪,可當(dāng)我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布昼汗。 她就那樣靜靜地躺著,像睡著了一般鬼雀。 火紅的嫁衣襯著肌膚如雪顷窒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天源哩,我揣著相機與錄音鞋吉,去河邊找鬼。 笑死励烦,一個胖子當(dāng)著我的面吹牛谓着,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坛掠,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼赊锚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屉栓?” 一聲冷哼從身側(cè)響起舷蒲,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎友多,沒想到半個月后牲平,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡域滥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年纵柿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骗绕。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡藐窄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出酬土,到底是詐尸還是另有隱情荆忍,我是刑警寧澤,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布,位于F島的核電站刹枉,受9級特大地震影響叽唱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜微宝,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一棺亭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蟋软,春花似錦镶摘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至湿痢,卻和暖如春涝缝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背譬重。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工拒逮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人臀规。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓滩援,卻偏偏與公主長得像,于是被迫代替她去往敵國和親塔嬉。 傳聞我的和親對象是個殘疾皇子狠怨,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,576評論 2 349

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