成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

React Hook 不完全指南

Lin_R / 2840人閱讀

摘要:使用完成副作用操作,賦值給的函數(shù)會(huì)在組件渲染到屏幕之后。如此很容易產(chǎn)生,并且導(dǎo)致邏輯不一致。同時(shí),這也是很多人將與狀態(tài)管理庫結(jié)合使用的原因之一。當(dāng)我們通過的第二個(gè)數(shù)組類型參數(shù),指明當(dāng)前的依賴,就能避免不相關(guān)的執(zhí)行開銷了。

前言
本文內(nèi)容大部分參考了 overreacted.io 博客一文,同時(shí)結(jié)合 React Hook 官方 文章,整理并歸納一些筆記和輸出個(gè)人的一些理解
什么是 Hook ?
官方介紹:Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。
React 中內(nèi)置的 Hook API

基礎(chǔ) Hook

useState

// 傳入初始值,作為 state
const [state, setState] = useState(initialState)

//  `惰性初始 state`;傳入函數(shù),由函數(shù)計(jì)算出的值作為 state
// 此函數(shù)只在初始渲染時(shí)被調(diào)用
const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props)
  return initialState
})

useEffect

該 Hook 接收一個(gè)包含命令式、且可能有副作用代碼的函數(shù).

在函數(shù)組件主體內(nèi)(這里指在 React 渲染階段)改變 DOM、添加訂閱、設(shè)置定時(shí)器、記錄日志以及執(zhí)行其他包含副作用的操作都是不被允許的,因?yàn)檫@可能會(huì)產(chǎn)生莫名其妙的 bug 并破壞 UI 的一致性。

使用 useEffect 完成副作用操作,賦值給 useEffect 的函數(shù)會(huì)在組件渲染到屏幕之后。你可以把 effect 看作從 React 的純函數(shù)式世界通往命令式世界的逃生通道。

默認(rèn)情況下,effect 將在每輪渲染結(jié)束后執(zhí)行,但你可以選擇讓它 在只有某些值改變的時(shí)候才執(zhí)行。詳情見后面。

清除 effect
通常,組件卸載時(shí)需要清除 effect 創(chuàng)建的諸如訂閱或計(jì)時(shí)器 ID 等資源。要實(shí)現(xiàn)這一點(diǎn),useEffect 函數(shù)需返回一個(gè)清除函數(shù)。以下就是一個(gè)創(chuàng)建訂閱的例子:

useEffect(() => {
  const subscription = props.source.subscribe()
  return () => {
    // 清除訂閱
    subscription.unsubscribe()
  }
}, [依賴])

useContext

額外的 Hook

useReducer

useCallback

useMemo

useRef

useImperativeHandle

useLayoutEffect

useDebugValue

我們?yōu)槭裁催x擇使用 Hook ? 1. 在組件之間復(fù)用狀態(tài)邏輯很難
React 沒有提供將可復(fù)用性行為“附加”到組件的途徑(例如,把組件連接到 store)。如果你使用過 React 一段時(shí)間,你也許會(huì)熟悉一些解決此類問題的方案,比如 render props 和 高階組件。但是這類方案需要重新組織你的組件結(jié)構(gòu),這可能會(huì)很麻煩,使你的代碼難以理解。如果你在 React DevTools 中觀察過 React 應(yīng)用,你會(huì)發(fā)現(xiàn)由 providers,consumers,高階組件,render props 等其他抽象層組成的組件會(huì)形成“嵌套地獄”。盡管我們可以在 DevTools 過濾掉它們,但這說明了一個(gè)更深層次的問題:React 需要為共享狀態(tài)邏輯提供更好的原生途徑。

你可以使用 Hook 從組件中提取狀態(tài)邏輯,使得這些邏輯可以多帶帶測試并復(fù)用。Hook 使你在無需修改組件結(jié)構(gòu)的情況下復(fù)用狀態(tài)邏輯。 這使得在組件間或社區(qū)內(nèi)共享 Hook 變得更便捷。

2. 復(fù)雜組件變得難以理解
我們經(jīng)常維護(hù)一些組件,組件起初很簡單,但是逐漸會(huì)被狀態(tài)邏輯和副作用充斥。每個(gè)生命周期常常包含一些不相關(guān)的邏輯。例如,組件常常在 componentDidMount 和 componentDidUpdate 中獲取數(shù)據(jù)。但是,同一個(gè) componentDidMount 中可能也包含很多其它的邏輯,如設(shè)置事件監(jiān)聽,而之后需在 componentWillUnmount 中清除。相互關(guān)聯(lián)且需要對照修改的代碼被進(jìn)行了拆分,而完全不相關(guān)的代碼卻在同一個(gè)方法中組合在一起。如此很容易產(chǎn)生 bug,并且導(dǎo)致邏輯不一致。

在多數(shù)情況下,不可能將組件拆分為更小的粒度,因?yàn)闋顟B(tài)邏輯無處不在。這也給測試帶來了一定挑戰(zhàn)。同時(shí),這也是很多人將 React 與狀態(tài)管理庫結(jié)合使用的原因之一。但是,這往往會(huì)引入了很多抽象概念,需要你在不同的文件之間來回切換,使得復(fù)用變得更加困難。

為了解決這個(gè)問題,Hook 將組件中相互關(guān)聯(lián)的部分拆分成更小的函數(shù)(比如設(shè)置訂閱或請求數(shù)據(jù)),而并非強(qiáng)制按照生命周期劃分。你還可以使用 reducer 來管理組件的內(nèi)部狀態(tài),使其更加可預(yù)測。

3. 用更少的代碼,實(shí)現(xiàn)同樣的效果

下面的代碼可以直觀的體現(xiàn)出來,在某些場景下,使用 hook 來實(shí)現(xiàn)對應(yīng)的功能,可以節(jié)省大部分的代碼

3.1 清除副作用更加緊湊

對比 Class 組件來說,清除副作用要簡單的多,如下代碼,在 useEffect hook 里面返回一個(gè)函數(shù),當(dāng)我們的函數(shù)組件卸載的時(shí)候,就會(huì)自動(dòng)執(zhí)行這個(gè)函數(shù),從而來清除副作用。想想我們在 Class 組件里面需要在 componentWillUnmount 生命周期里面去編寫對應(yīng)的代碼。

對比兩者我們發(fā)現(xiàn),使用 useEffect 的方式,能夠?qū)燧d和卸載的邏輯更加緊密的耦合在一起,從而減少 BUG 的發(fā)生

useEffect(() => {
  const id = setInterval(() => {
    setCount(count => count + 1)
  }, 1000)
  return () => clearInterval(id)
}, [])

// 比如給 windows 掛載監(jiān)聽函數(shù)
useEffect(() => {
  window.addEventListener("reszie", handleRezie)

  return () => {
    window.removeEventListener("resize", handleRezie)
  }
}, [])
如何正確的使用 Hook ? 1. 使用規(guī)則

只在最頂層使用 Hook:不要在循環(huán),條件或嵌套函數(shù)中調(diào)用 Hook, 確??偸窃谀愕?React 函數(shù)的最頂層調(diào)用他們。

不要在普通的 JavaScript 函數(shù)中調(diào)用 Hook。你可以

[x] 在 React 的函數(shù)組件中調(diào)用 Hook

[x] 在自定義 Hook 中調(diào)用其他 Hook

2. 只有在自己依賴更新時(shí)才執(zhí)行 effect

使用 useEffect 完成副作用操作,賦值給 useEffect 的函數(shù)會(huì)在組件渲染到屏幕之后;牢記這句話。

仔細(xì)觀察如下代碼,當(dāng)函數(shù)組件里面,有多個(gè) effect 的時(shí)候,默認(rèn)的 effect 將在每次 UI render 之后被調(diào)用。當(dāng)我們通過 useEffect 的第二個(gè)數(shù)組類型參數(shù),指明當(dāng)前 effect 的依賴,就能避免不相關(guān)的執(zhí)行開銷了。

通過啟用 eslint-plugin-react-hooks 插件,來強(qiáng)制提醒我們在使用 effect 的時(shí)候,申明所需要的依賴

{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error",
    "react-hooks/exhaustive-deps": "warn"
  }
}
const CounterHook = () => {
  const [count, setCount] = useState(0)
  const [name, setName] = useState("heaven")

  useEffect(() => {
    document.title = `counterWithHook ${count}`
  }, [count])

  useEffect(() => {
    console.log("you name is", name)
  }, [name])

  return (
    

Counter with Hook

You click {count} times

setName(e.target.value)} />
your name is {name}

) }
2.1 不要忘記函數(shù)依賴

對于 useEffect 內(nèi)部方法,一旦引用外部的函數(shù),那么這個(gè)時(shí)候需要注意了:
需要把 useEffect 內(nèi)部引用到的方式,聲明為當(dāng)前 effect 的依賴
在下圖的代碼中,我們可以看到,在 effect 函數(shù)內(nèi)部,引入外部的函數(shù),我們的 eslint-plugin-react-hooks 插件會(huì)自動(dòng)提示我們需要把對應(yīng)的函數(shù)作為依賴添加進(jìn)去

不規(guī)范示例:這里在安裝了插件的情況下,會(huì)自動(dòng)提示我們將 fetchData 函數(shù)移入 effect 內(nèi)部

const getFetchUrl = () => {
  return `https://hn.algolia.com/api/v1/search?query=${query}`
}

const fetchData = async () => {
  return axios.get(getFetchUrl())
}

useEffect(() => {
  fetchData().then(resp => {
    console.log(resp)
    setData(resp.data)
  })
}, [])

正確的寫法:

useEffect(() => {
  const getFetchUrl = () => {
    return `https://hn.algolia.com/api/v1/search?query=${query}`
  }

  const fetchData = async () => {
    return axios.get(getFetchUrl())
  }

  fetchData().then(resp => {
    console.log(resp)
    setData(resp.data)
  })
}, [query])
3、理解每一次的 Rendering
每一次渲染都有它自己的 Props and State
每一次渲染都有它自己的事件處理函數(shù)
每次渲染都有它自己的 Effects

運(yùn)行如下代碼之后,在我們點(diǎn)擊 Show alert 按鈕之后,然后點(diǎn)擊 Click me 按鈕,alert 輸出的永遠(yuǎn)是在點(diǎn)擊的那個(gè)時(shí)刻的 count;

換句話來說;在 hooks 組件里面,每一次的渲染,都相當(dāng)于記錄當(dāng)前次的『快照』

import React, { useEffect, useState } from "react"
const Counter = () => {
  const [count, setCount] = useState(0)

  const handleAlertClick = () => {
    setTimeout(() => {
      alert(`Yout clicked me: ${count}`)
    }, 3000)
  }

  useEffect(() => {
    setTimeout(() => {
      console.log(`Yout clicked ${count} times`)
    }, 3000)
  })

  return (
    

You clicked {count} times

) } export default Counter
使用自定義 Hook
通過自定義 Hook,可以將組件邏輯提取到可重用的函數(shù)中。

當(dāng)我們想在兩個(gè)函數(shù)之間共享邏輯時(shí),我們會(huì)把它提取到第三個(gè)函數(shù)中。而組件和 Hook 都是函數(shù),所以也同樣適用這種方式。

自定義 Hook 是一個(gè)函數(shù),其名稱以 “use” 開頭,函數(shù)內(nèi)部可以調(diào)用其他的 Hook。

自定義 useService hook

useService.js 自定義的一個(gè) server hook,該 hook 封裝了 ajax 請求中的 { loading, error, response } 三個(gè)基礎(chǔ)邏輯;有了這個(gè) hook 我們就能很輕松的在每次網(wǎng)絡(luò)請求里面去處理各種異常邏輯了;詳細(xì)用法看文章最后的 Table 分頁操作實(shí)例

import { useEffect, useRef, useState, useCallback } from "react"
import { isEqual } from "lodash"

const useService = (service, params) => {
  const prevParams = useRef(null)
  const [callback, { loading, error, response }] = useServiceCallback(service)

  useEffect(() => {
    if (!isEqual(prevParams.current, params)) {
      prevParams.current = params
      callback(params)
    }
  })

  return { loading, error, response }
}

const useServiceCallback = service => {
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)
  const [response, setResponse] = useState(null)

  // 使用 useCallback,來判斷 service 是否改變
  const callback = useCallback(
    params => {
      setLoading(true)
      setError(null)
      service(params)
        .then(response => {
          console.log(response)
          setLoading(false)
          setResponse(response)
        })
        .catch(error => {
          setLoading(false)
          setError(error)
        })
    },
    [service]
  )

  return [callback, { loading, error, response }]
}
實(shí)例剖析 Table 分頁操作

如下代碼,使用 hook 的方式來實(shí)現(xiàn)表格的分頁,數(shù)據(jù)請求操作,

跑馬燈中獎(jiǎng)

使用 hook 實(shí)現(xiàn)一個(gè)簡易版的跑馬燈抽獎(jiǎng)邏輯

參考資料

官方 Hook 介紹
Hook 規(guī)則
Hook API 索引
如何在 Hook 中發(fā)起請求
useEffect 詳解

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/109624.html

相關(guān)文章

  • React Hook起飛指南

    摘要:起飛指南作者元瀟方凳雅集出品目前放出來了個(gè)內(nèi)置,但僅僅基于以下兩個(gè),就能做很多事情。行代碼實(shí)現(xiàn)一個(gè)全局元瀟根組件掛上即可子組件調(diào)用隨時(shí)隨地實(shí)現(xiàn)一個(gè)局部元瀟的本質(zhì)是的一個(gè)語法糖,感興趣可以閱讀一下的類型定義和實(shí)現(xiàn)。 React Hook起飛指南 作者:元瀟 方凳雅集出品 16.8目前放出來了10個(gè)內(nèi)置hook,但僅僅基于以下兩個(gè)API,就能做很多事情。所以這篇文章不會(huì)講很多API,...

    姘擱『 評論0 收藏0
  • 理解 React Hooks 的 Capture Value 特性

    摘要:在讀了一些文章后,大致是找到自己總是掉坑的原因了沒理解中的特性。通過這個(gè)示例,相信會(huì)比較容易地理解特性,并如何使用來暫時(shí)繞過它。在知道并理解這個(gè)特性后,有助于進(jìn)一步熟悉了的運(yùn)行機(jī)制,減少掉坑的次數(shù)。 由于剛使用 React hooks 不久,對它的脾氣還拿捏不準(zhǔn),掉了很多次坑;這里的 坑 的意思并不是說 React hooks 的設(shè)計(jì)有問題,而是我在使用的時(shí)候,因?yàn)檫€沒有跟上它的理念導(dǎo)...

    curlyCheng 評論0 收藏0
  • React教程:組件,Hooks和性能

    摘要:顧名思義,受控組件的值由控制,能為與用戶交互的元素提供值,而不受控制的元素不獲取值屬性。另外我發(fā)現(xiàn)受控組件更容易理解和于使用。只是一種把組件作為參數(shù)的函數(shù),并且與沒有包裝器的組件相比,能夠返回具有擴(kuò)展功能的新組件。其中三個(gè)基本的是,和。 翻譯:瘋狂的技術(shù)宅原文:https://www.toptal.com/react/... 本文首發(fā)微信公眾號:jingchengyideng歡迎關(guān)...

    edagarli 評論0 收藏0
  • react hook實(shí)用的用法和技巧分析

    摘要:以我個(gè)人的觀點(diǎn),要不要使用呢建議用的的人項(xiàng)目版本已經(jīng)是了新建的項(xiàng)目一直對新技術(shù)保持關(guān)注,躍躍欲試的人對函數(shù)式編程愛好的人對的,,厭煩,甚至因?yàn)橹匦落秩菊煸陬^疼的人不建議用的人對極其厭惡,對生命周期編程是非愛好的人。 react hook發(fā)布也已經(jīng)有幾個(gè)月了,相信有部分人已經(jīng)開始使用了,還有些人在猶豫要不要用,可能更多人安于現(xiàn)狀,沒有要用的打算,甚至還有很多公司的react版本是15或...

    CntChen 評論0 收藏0
  • 10分鐘了解react新特性hooks

    摘要:簡介是的新增特性。我們統(tǒng)一把這些操作稱為副作用,或者簡稱為作用。由于副作用函數(shù)是在組件內(nèi)聲明的,所以它們可以訪問到組件的和。副作用函數(shù)還可以通過返回一個(gè)函數(shù)來指定如何清除副作用。目前為止,有兩種主流方案來解決這個(gè)問題高階組件和。 Hook 簡介 Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。 us...

    hlcfan 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<