最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

react中hook介紹以及使用教程

 更新時間:2020年12月11日 09:34:14   作者:care_yourself  
這篇文章主要給大家介紹了關(guān)于react中hook及使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

最近由于公司的項目開發(fā),就學(xué)習(xí)了在react關(guān)于hook的使用,對其有個基本的認識以及如何在項目中去應(yīng)用hook。在這篇博客中主要從以下的幾個點進行介紹:

  • hook簡介
  • hook中常用api的使用
  • hook在使用過程中需要去注意的地方
  • hook中怎樣去實現(xiàn)class組件中的聲明周期函數(shù)

hook

首先介紹關(guān)于hook的含義,以及其所要去面對的一些場景

含義:Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。簡單來說就是可以使用函數(shù)組件去使用react中的一些特性

所要解決的問題:

  • 解決組件之間復(fù)用狀態(tài)邏輯很難得問題,hook能解決的就是在你無需修改之前組件結(jié)構(gòu)的情況下復(fù)用狀態(tài)邏輯,在不使用hook的情況下,需要使用到一些高級的用法如高級組件、provider、customer等,這種方式對于新手來說不太友好,可能在理解上就比較的困難
  • 對于復(fù)雜組件可以去拆分其邏輯,例如在你使用生命周期函數(shù)時,不同的生命周期需要在不同的時刻進行,因此在此時對于復(fù)雜的組件來說,有的生命周期函數(shù)中就存在大量的邏輯,在可讀性上面就大打折扣。當使用hook時,就可以進行組件邏輯的劃分,將相同的邏輯給整合在一起,這樣就大大增加可讀性也在一方面利于維護
  • 不需要對于class組件的理解,當你在最初去學(xué)習(xí)時,你不得不去理解this這個關(guān)鍵字,在當前組件所表示的含義,但是在hook中就不需要。能夠解決你在不使用class組件的情況下去體現(xiàn)react的特性
  • 需要注意的一點就是hook和class組件是不能夠同時使用的,在實際的使用過程中一定要注意,否則就會出現(xiàn)報錯

那么接下來所要介紹的部分就是如何去使用hook

state hook

對于使用過class組件的同學(xué),相信對于state肯定有很深的印象,對于一些需要用到的全局變量,在class組件中我們常常采用的方式是this.state = {},但是在hook中我們采用的方式就是使用useState這個hook,然后就可以對這種全局變量進行引用,在引用時只需要用其變量名即可,這里就拿官網(wǎng)的例子來舉例:
import React, { useState } from 'react';

import React, { useState } from 'react';

function Example() {
 // 聲明一個叫 "count" 的 state 變量
 const [count, setCount] = useState(0);

 return (
 <div>
  <p>You clicked {count} times</p>
  <button onClick={() => setCount(count + 1)}>
  Click me
  </button>
 </div>
 );
}

在上面的這個例子中,我們設(shè)置變量方式采用的就是const [count, setCount] = useState(0)這種方式,其中的0就是給count賦初值為0,如果想要給count賦值為一個空對象,那么只需要const [count, setCount] = useState({}),這樣的方式就行了,那么這樣你在用count時,此時獲取到的值就為一個空對象。

作用:返回一個state,以及更新state的函數(shù)

  1. 函數(shù)式更新:新的state需要通過使用先前的state計算得出,將函數(shù)傳遞給setState,該函數(shù)將接收先前的state,并返回一個更新后的值
  2. 惰性初始state,initialState參數(shù)只會在組件的初始渲染中起作用,如果初始化state需要通過一個復(fù)雜計算來獲取,則可以傳入一個函數(shù),在函數(shù)中計算并返回初始的state,此函數(shù)只在初始渲染時被掉用,如下所示:
 const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
 })

在hook中如何給全局變量設(shè)置值

在class組件中我們給放在state中的變量賦值時,通常采用的方式就是this.setState()這種方式,那么在hook中所要采用的就是set+變量名這種方式,如

const [count, setCount] = useState(0)

在這里通過上面我們已經(jīng)知道的就是count能夠獲取到值,那么其所對應(yīng)的setCount(值),這種賦值的方式就是給count變量賦值的,然后通過count就能夠獲取到值。

  • 為什么要采用這種方式呢?
  • 原因:是因為react中的單向數(shù)據(jù)源,這樣的話,能夠保證你的數(shù)據(jù)源流向會更加的清楚,這也是react所區(qū)別于vue中雙向數(shù)據(jù)源綁定的一點

hook中設(shè)置多個全局變量的方式

在hook中,如果我們需要去設(shè)置多個類似于上面所說的count,那么就需要多次使用useState這個hook,當然你也可以設(shè)置一個變量在hook的最外部,即在hook這個函數(shù)組件的外部。需要注意的是別在整個hook這個函數(shù)的全局設(shè)置,因此在hook的運行機制中,在每次加載時,都會從新去加載里面的變量,因此你是不能夠去獲取到在整個函數(shù)內(nèi)部中使用該變量所改變的值的,能夠獲取到的就只是這個變量的初始值*

useEffect hook

對于useEffect hook,其用途類似于class組件中的生命周期函數(shù),用來處理在一些特定時刻需要去做的事情,這種事情常被叫做副作用。在使用useEffect這個hook時,需要注意的一點就是其不能夠被包含在循環(huán),判斷語句中,否則項目會出現(xiàn)報錯,這也是hook的一種設(shè)置機制

  • 副作用的劃分:
    • 不需要清除的: 在React更新DOM之后運行一些額外的代碼:如:發(fā)送網(wǎng)絡(luò)請求,手動變更DOM,記錄日志等
    • 需要清除的:當使用外部數(shù)據(jù)源時,需要去清除數(shù)據(jù),如:定時器,需要我們在結(jié)束的時候去清除
  • 渲染時機:在使用useEffect這個hook時,需要注意的就是其渲染的時機,默認情況下會在第一次渲染和每一次更新時去執(zhí)行。對于如何去控制這個渲染時機,在下面的一個部分會有詳細的介紹
  • 作用:告訴組件在渲染之后執(zhí)行某些操作
  • useEffect放在組件內(nèi)部調(diào)用的原因:可以在effect中直接訪問state中的變量
  • effect返回函數(shù):effect可選的清除機制,每個effect都可以返回一個清除函數(shù)
  • 接收內(nèi)容:一個包含命令式、并且可能有副作用代碼的函數(shù)
  • 清除effect:實現(xiàn)方式,effect函數(shù)需要返回一個清除函數(shù)
  • effect執(zhí)行時機:在瀏覽器完成布局和繪制之后,傳給useEffect的函數(shù)會延遲調(diào)用,因此不應(yīng)該在函數(shù)中執(zhí)行足賽瀏覽器更新屏幕的操作。
  • 默認條件執(zhí)行:會在每輪組件渲染完成后執(zhí)行,因而一旦effect的依賴發(fā)生變化,他就會被重新創(chuàng)建。要改變其執(zhí)行時機,需要給useEffect傳遞第二個參數(shù),只有當?shù)诙€參數(shù)值發(fā)生改變才會重新創(chuàng)建訂閱。如果要使用這個優(yōu)化的方式,需要確保數(shù)組包含了所有外部作用域中會發(fā)發(fā)生變化,且在effect中使用的變量。如果只想運行一次effect,可以傳遞一個空數(shù)組作為第二個參數(shù)。

對于useEffect的初步認識只需要了解上面的即可。接下來就來介紹一個官網(wǎng)的實例,來說明useEffect

import React, { useState, useEffect } from 'react';

function Example() {
 const [count, setCount] = useState(0);

 // Similar to componentDidMount and componentDidUpdate:
 useEffect(() => {
  // Update the document title using the browser API
  document.title = `You clicked ${count} times`;
 });

 return (
  <div>
   <p>You clicked {count} times</p>
   <button onClick={() => setCount(count + 1)}>
    Click me
   </button>
  </div>
 );
}

在上面的這段代碼中,就使用到了useEffect這個hook,在每次count值改變時,就會在頁面中去打印“You clicked ${count} times”這段文字,當然count肯定對應(yīng)的就是其所對應(yīng)的值。

useEffect去取代calss中的生命周期函數(shù)的方式

react中有狀態(tài)組件中,其生命周期函數(shù)的各個階段

  1. 在Mounting階段
    1. constructor()
    2. static getDerivedStateFromProps()
    3. render()
    4. componentDidMount()
  2. Updating
    1. static getDerivedStateFormProps
    2. shouldComponentUpdate()
    3. render()
    4. getSnapshotBeforeUpdate()
    5. componentDidUpdate()
  3. UnMouting
    1. componentWillUnmount()

使用hook去代替生命周期函數(shù)的方式

這里就介紹了關(guān)于useEffect這個hook的使用,有一些生命周期函數(shù)就是通過該hook來實現(xiàn)的,這里推薦一篇文章https://blog.logrocket.com/guide-to-react-useeffect-hook/,可以參考下。這里是在參考了一些文章后寫的,具體介紹如下:

constructor: 可以通過useState來初始化state

componentDidMount(),在hook中需要使用下面的這種方式去取代,在useEffect中傳遞第二個參數(shù),該參數(shù)為一個空數(shù)組,只會去執(zhí)行一次,如下面所示

useEffect(() => {

},[])

componentDidUpdate(),有兩種方式去解決

在每次渲染的時候都去調(diào)用hooks,解決的方式如下面所示

  useEffect(() => {

  })

用一個特殊變量的去觸發(fā)hook,如下面所示,count指的就是這個特殊的變量,該hook觸發(fā),只會是count的值改變時

  useEffect(() => {

  },[count])

componentWillUnmount(),用hook來代替,需要去return一個callback(回調(diào)函數(shù)),如下面的形式所示

  useEffect(() => {
    return () => {
      //執(zhí)行的為componentWillUnmount
    }
  },[])

shouldComponentUpdata(),常使用React.memo來代替,在默認情況下,它將對props對象中的復(fù)雜對象進行淺層比較,如果想要去控制比較,可以去提供一個自定義的比較函數(shù)作為第二個參數(shù)。代替hook的方式如下所示

  import React from 'react'
  function areEqual(prevProps, nextProps) {
  /*
  return true if passing nextProps to render would return
  the same result as passing prevProps to render,
  otherwise return false
  */
  }
  const Weather = ({weather}) => {
    return (<div>
        <p>{weather.city}</p>
        <p>{weather.temperature}</p>
        {console.log('Render')}
        </div>
    )
  }

  export default React.memo(Weather, areEqual)

自定義hook

通常在實際的項目開發(fā)中少不了使這種自定義的hook,前提是在整個項目中使用了hook的情況下。通常情況下就是去使用useState,useEffect這種系統(tǒng)已經(jīng)定義好的hook去實現(xiàn),在調(diào)用時你就可以直接調(diào)用當你自定義好的hook來實現(xiàn)你所需要的功能。下面就以自定義useReducer這個hook為例

import React, { useEffect } from 'react'

function useReducer(reducer, initialState) {
 const [state, setState] = useState(initialState);

 function dispatch(action) {
  const nextState = reducer(state, action);
  setState(nextState);
 }

 return [state, dispatch];
}
export default useReducer

在上面的這個實際例子中,我們封裝了一個自定義的useReducerhook,我們可以調(diào)用這個hook去完成與reducer一樣的功能了,在調(diào)用是就需要我們?nèi)魅雰蓚€參數(shù),一個就是reducer,另外一個就是initialState,然后就能夠取得state,以及dispatch方法。注意這里的返回值使用的是一個數(shù)組,這樣的好處就是我們在獲取其返回值時,可以采用數(shù)組結(jié)構(gòu)這種方式來獲取。具體關(guān)于數(shù)組的結(jié)構(gòu)可以去看看es6中的部分,就能夠明白了。那么接下來就是使用這個自定義好的useReducer。使用方式如下

import useReducer form '你封裝useRecuer的組件中'
function Todos() {
const todosReducer = ( state, dispatch) => {
	if(dispatch.type == "") { //type值為什么時去執(zhí)行
		const newState == "" //執(zhí)行一些操作,去更新state
		return newState //返回新的neState
	}
}
 const [todos, dispatch] = useReducer(todosReducer, []);
 function handleAddClick(text) {
  dispatch({ type: 'add', text });
 }

 return (
	<div></div>
)
}

這里并沒有把實際的使用情況給寫完,剩余的可以自己去補充,其使用方式就和redux的使用方式相同。這就是整個自定義hook以及去使用的過程,在實際的開發(fā)中可以去體驗體驗。

額外的hook

useReducer,能給那些會出發(fā)深更新的組件做性能優(yōu)化,因為可以向子組件去傳遞dispatch而不是回調(diào)

useReducer這個hook的封裝,整個封裝的方法如下:

//reducer hook封裝
  import { useState } from 'react';
  export default useReducer function(reducer, initialState) {
    const [state, setState] = useState(initialState);
    function dispatch(action){
      const nextState = reducer(state, action);
      return setState(nextState);
    }
    return [state, dispatch]
  }
//實際例子使用
  import useReducer from '';
  const initialState = {count: 0};
  function reducer(state, action) {
  switch (action.type) {
    case 'increment':
    return {count: state.count + 1};
    case 'decrement':
    return {count: state.count - 1};
    default:
    throw new Error();
  }
  }
  return (
    <div>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'devrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </div>
  )

useReducer的惰性初始化,可以選擇惰性地創(chuàng)建初始化state。因此需要設(shè)置一個初始化函數(shù)作為useReducer的第三個參數(shù)傳入,這樣初始化state將設(shè)置為init(initialArg),如下所示,就是一個實際的案例在useReducer中去傳遞第三個參數(shù)

function init(initialCount) {
 return {count: initialCount};
}

function reducer(state, action) {
 switch (action.type) {
  case 'increment':
   return {count: state.count + 1};
  case 'decrement':
   return {count: state.count - 1};
  case 'reset':
   return init(action.payload);
  default:
   throw new Error();
 }
}

function Counter({initialCount}) {
 const [state, dispatch] = useReducer(reducer, initialCount, init);
 return (
  <>
   Count: {state.count}
   <button
    onClick={() => dispatch({type: 'reset', payload: initialCount})}>
    Reset
   </button>
   <button onClick={() => dispatch({type: 'decrement'})}>-</button>
   <button onClick={() => dispatch({type: 'increment'})}>+</button>
  </>
 );
}

注意:如果reducer hook的返回值與當前state相同,react將跳過子組件的渲染及副作用的執(zhí)行

useCallback

返回值:返回一個memoized回調(diào)函數(shù),該回調(diào)函數(shù)僅在某給依賴項改變時才會更新。

含義:把內(nèi)聯(lián)回調(diào)函數(shù)及其依賴項數(shù)組作為參數(shù)傳入useCallback,它將返回該回調(diào)函數(shù)傳遞給經(jīng)過優(yōu)化的并使用引用相等性去避免非必要渲染

useCallBack(fn, deps)相當與useMemo(() => fn,deps)

useMemo

使用方式:const memoziedValue = useMemo(() => computeExpensiveValue(a,b), [a, b])

返回值:返回一個memoized值,把創(chuàng)建函數(shù)和依賴項數(shù)組作為參數(shù)傳入useMemo,僅在某個依賴項改變時才重新計算memoized值。

好處:這種優(yōu)化有助于避免在每次渲染時都進行高開銷的計算

渲染方式:傳入useMemo的函數(shù)會在渲染期間執(zhí)行,不要在這個函數(shù)內(nèi)部執(zhí)行與渲染無關(guān)的操作,如屬于useEffect中的副作用。如果沒有,那么新的值將會在每次渲染時被重新渲染

注意:依賴項數(shù)組不會作為參數(shù)傳遞給函數(shù),概述來說,就是每一個出現(xiàn)在函數(shù)中的參數(shù)也應(yīng)該出現(xiàn)在依賴項的數(shù)組中

useRef

使用方式: const refContainer = useref(initialValue);

返回值:返回一個可ref對象,其.current屬性被初始化為傳入的參數(shù)(initialValue)。這返回的的對象將在組件的整個生命周期中持續(xù)

含義: useRef就像是一個盒子可以將.current中得可變屬性給保存起來

ref與useRef的區(qū)別在于,后者是創(chuàng)建的了一個普通的js對象,useRef和自建一個{current: …。}對象的唯一區(qū)別是,useRef會在每次渲染時,返回同一個ref對象

useImperativeHandle

作用:可以在使用ref時自定義暴露給賦組件的實例值,使用的形式如下:

useImperativeHandle(ref, createHandle, [deps])

useLayoutEffect

更新時機:在瀏覽器執(zhí)行下一次繪制前去執(zhí)行

與useEffect相同,會在所有的DOM變更之后同步調(diào)用effect

useDebugValue

作用:在react devTools中常被用于去當作展示標簽,作為客戶端的鉤子

hooks中的性能優(yōu)化

在hook中,其性能優(yōu)化的點很多,這個可以在一些https://react.docschina.org/docs/hooks-faq.html#performance-optimizations去學(xué)習(xí),下面是我看的一部分。

如何在更新時去跳過effect,可以采用條件式方式,即在useEffect中去傳遞第二個參數(shù)

由于某些原因,無法將一個函數(shù)移動到effect內(nèi)部時,可采用下面方式

  1. 嘗試將函數(shù)移動到當前組件的外部
  2. 如果所調(diào)用對策方法是一個純計算等,此時可以在effect外面去寫這個函數(shù)
  3. 如果要增加一個函數(shù)去依賴項,那么要明確使用useCallback外部的hook,如下面的例子所示
function ProductPage({ productId }) {
// Wrap with useCallback to avoid change on every render
const fetchProduct = useCallback(() => {
  // ... Does something with productId ...
}, [productId]); // All useCallback dependencies are specified

return <ProductDetails fetchProduct={fetchProduct} />;
}

function ProductDetails({ fetchProduct }) {
useEffect(() => {
  fetchProduct();
}, [fetchProduct]); // All useEffect dependencies are specified
// ...
}

實現(xiàn)shouldComponentUpdate的方式

  const Button = React.memo((props) => {
  // your component
  });

如上面所示,這種實現(xiàn)方式并不是使用了hooks,它相當于純組件,但是僅僅能夠比較的是props??梢匀ピ黾拥诙€參數(shù),采用一種函數(shù)的方式去拿到新老的props,如果結(jié)果返回true,就跳過更新階段

記住計算結(jié)果的方式

使用useMemo這個hook去記住之前的計算結(jié)果,從而在多個渲染之中緩存計算

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

上面的代碼會調(diào)用computeExpensiveValue(a,b)這個函數(shù),但是它們依賴的a,b沒有改變,那么useMemo在直接去返回上一次結(jié)果的值

結(jié)語

對于hook的學(xué)習(xí)大概就如上面所說,對于hook其中的內(nèi)容還很多所以對于hook的學(xué)習(xí)最好是去官網(wǎng)看看,鏈接如下https://react.docschina.org/docs/hooks-intro.html在官網(wǎng)中介紹的更加詳細,這里的中文文檔和英文文檔內(nèi)容都一樣,不過對于英文好的同學(xué)建議看看英文版本。

到此這篇關(guān)于react中hook的介紹以及使用的文章就介紹到這了,更多相關(guān)react中hook介紹及使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React useImperativeHandle處理組件狀態(tài)和生命周期用法詳解

    React useImperativeHandle處理組件狀態(tài)和生命周期用法詳解

    React Hooks 為我們提供了一種全新的方式來處理組件的狀態(tài)和生命周期,useImperativeHandle是一個相對較少被提及的Hook,但在某些場景下,它是非常有用的,本文將深討useImperativeHandle的用法,并通過實例來加深理解
    2023-09-09
  • 詳解react-native-fs插件的使用以及遇到的坑

    詳解react-native-fs插件的使用以及遇到的坑

    本篇文章主要介紹了react-native-fs插件的使用以及遇到的坑,詳細的介紹了react-native-fs安裝使用,具有一定的參考價值,有興趣的可以了解一下
    2017-09-09
  • 詳解使用React進行組件庫開發(fā)

    詳解使用React進行組件庫開發(fā)

    本篇文章主要介紹了詳解使用React進行組件庫開發(fā),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • React封裝CustomSelect組件思路詳解

    React封裝CustomSelect組件思路詳解

    小編需要封裝一個通過Popover彈出框里可以自定義渲染內(nèi)容的組件,渲染內(nèi)容暫時有: 單選框, 復(fù)選框,接下來通過本文給大家分享React封裝CustomSelect組件思路,需要的朋友可以參考下
    2022-07-07
  • React Hooks之useRef獲取元素示例詳解

    React Hooks之useRef獲取元素示例詳解

    這篇文章主要介紹了React Hooks之useRef獲取元素示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • React?Hooks使用startTransition與useTransition教程示例

    React?Hooks使用startTransition與useTransition教程示例

    這篇文章主要為大家介紹了React?Hooks使用startTransition與useTransition教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • 實現(xiàn)React單頁應(yīng)用的方法詳解

    實現(xiàn)React單頁應(yīng)用的方法詳解

    今天我們來學(xué)習(xí)React是如何構(gòu)建起一個單頁應(yīng)用的,React作為目前最流行的前端框架之一,其受歡迎程度不容小覷,從這門框架上我們可以學(xué)到許多其他前端框架所缺失的東西,也是其創(chuàng)新性所在的地方,比如虛擬DOM、JSX等。下面一起來看看。
    2016-08-08
  • React組件的生命周期深入理解分析

    React組件的生命周期深入理解分析

    組件的生命周期就是React的工作過程,就好比人有生老病死,自然界有日月更替,每個組件在網(wǎng)頁中也會有被創(chuàng)建、更新和刪除,如同有生命的機體一樣
    2022-12-12
  • React 模塊聯(lián)邦多模塊項目實戰(zhàn)詳解

    React 模塊聯(lián)邦多模塊項目實戰(zhàn)詳解

    這篇文章主要介紹了React 模塊聯(lián)邦多模塊項目實戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • React經(jīng)典面試題之倒計時組件詳解

    React經(jīng)典面試題之倒計時組件詳解

    這些天也都在面試,面試的內(nèi)容也大多千篇一律,無外乎vue、react這些框架的一些原理,和使用方法,但是也遇到些有趣的題目,這篇文章主要給大家介紹了關(guān)于React經(jīng)典面試題之倒計時組件的相關(guān)資料,需要的朋友可以參考下
    2022-03-03

最新評論

金沙县| 务川| 凯里市| 那曲县| 文水县| 金坛市| 云梦县| 阜南县| 高要市| 广水市| 玛曲县| 手机| 静安区| 苏尼特左旗| 乡宁县| 承德市| 社旗县| 新河县| 深圳市| 道真| 锦屏县| 莆田市| 宽城| 舒兰市| 宁波市| 枣阳市| 汝南县| 苗栗市| 库尔勒市| 杭州市| 漳州市| 辽宁省| 浏阳市| 泰和县| 大石桥市| 上杭县| 白城市| 页游| 邮箱| 云南省| 乐昌市|