日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

React hooks解析(useState、useEffect、userReducer、useCallback、useMemo、userContext、useRef)

發布時間:2023/12/29 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 React hooks解析(useState、useEffect、userReducer、useCallback、useMemo、userContext、useRef) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是Hooks?

'Hooks'的單詞意思為“鉤子”。React Hooks 的意思是,組件盡量寫成純函數,如果需要外部功能和副作用,就用鉤子把外部代碼"鉤"進來。而React Hooks 就是我們所說的“鉤子”。

常用的鉤子

useState()
useEffect()
userReducer()
useCallback()
useMemo()
useContext()
useRef()

一、userState():狀態鉤子

純函數組件沒有狀態,useState()用于為函數組件引入狀態。在useState()中,數組第一項為一個變量,指向狀態的當前值。類似this.state,第二項是一個函數,用來更新狀態,類似setState。

import React, {useState} from 'react'
const AddCount = () => {
  const [ count, setCount ] = useState(0)
  return (
    <div>
      <button onClick={()=>setCount(count++)}>加一</button>
    </>
  )
}
export default AddCount 

二、useEffect():副作用鉤子

useEffect()接受兩個參數,第一個參數是你要進行的異步操作,第二個參數是一個數組,用來給出Effect的依賴項。只要這個數組發生變化,useEffect()就會執行

useEffect()可以看做componentDidMount,componentDidUpdate 和 componentWillUnmount這三個函數的組合。

useEffect(
  () => { 
    const subscription = props.source.subscribe();
    return () => {//相當于ComponentWillUnmount
      subscription.unsubscribe();
    };
  },
  [props.source],//相當于ComponentDidUpdate
);

三、useReducer():Action鉤子

我們通過用戶在頁面中發起action,從而通過reducer方法來改變state,從而實現頁面和狀態的通信。

const [state, dispatch] = useReducer(reducer, initialState)

它接受reducer函數和狀態的初始值作為參數,返回一個數組,其中第一項為當前的狀態值,第二項為發送action的dispatch函數。下面我們依然用來實現一個計數器。

const reduer = (state, action) => {
    switch(action) {
        case 'add': return state + 1;
        case 'reduce': return state - 1;
        case 'reset': return 0;
        default:return state;
  }
}

函數組件:

import React,{useReducer} from 'react'
export default function Counter() {
     const [counter, dispatch] = useReducer(reduer, 0);
}
return (
    <div >
          <div>{counter}</div>
          <Button onClick={() => dispatch('add')}>遞增</Button>
          <Button onClick={() => dispatch('reduce')}>遞減</Button>
          <Button onClick={() => dispatch('reset')}>重置</Button>
    </div>
  );
}

useState是useReducer的一個子集,useState 返回的函數內部封裝了一個 dispatch。useReducer( 單個組件中用的少,太重了)

官方的定義:在某些場景下,useReducer會比useState更適用,例如 state 邏輯較復雜且包含多個子值(注意且字),或者下一個 state 依賴于之前的 state 等。

四、useCallback和useMemo

useMemo 和 useCallback 接收的參數都是一樣,第一個參數為回調,第二個參數為要依賴的數據

共同作用:僅僅依賴數據發生變化, 才會調用,也就是起到緩存的作用。useCallback緩存函數,useMemo 緩存返回值。

useCallback使用場景

有一個父組件,其中包含子組件,子組件接收一個函數作為props;通常而言,如果父組件更新了,子組件也會執行更新;所有依賴本地狀態或props來創建函數,需要使用到緩存函數的地方,都是useCallback的應用場景。

父組件:

import React, { useCallback } from 'react'

function ParentComp () {
  // ...
  const [ name, setName ] = useState('hi~')
  // 每次父組件渲染,返回的是同一個函數引用
  const changeName = useCallback((newName) => setName(newName), [])  
  return (
    <div>
      <button onClick={increment}>點擊次數:{count}</button>
      <ChildComp name={name} onClick={changeName}/>
    </div>
  );
}

子組件

import React, { memo } from 'react'

const ChildComp = memo(function ({ name, onClick }) {
  console.log('render child-comp ...')
  return <>
    <div>Child Comp ... {name}</div>
    <button onClick={() => onClick('hello')}>改變 name 值</button>
  </>
})

點擊父組件按鈕,控制臺不會打印子組件被渲染的信息了。

究其原因:useCallback() 起到了緩存的作用,即便父組件渲染了,useCallback() 包裹的函數也不會重新生成,會返回上一次的函數引用。

useMemo

import React, { useCallback } from 'react'

function ParentComp () {
  // ...
  const [ name, setName ] = useState('hi~')
  const [ age, setAge ] = useState(20)
  const changeName = useCallback((newName) => setName(newName), [])
  const info = { name, age }    // 復雜數據類型屬性

  return (
    <div>
      <button onClick={increment}>點擊次數:{count}</button>
      <ChildComp info={info} onClick={changeName}/>
    </div>
  );
}

父組件渲染,const info = { name, age }一行會重新生成一個新對象,導致傳遞給子組件的 info 屬性值變化,進而導致子組件重新渲染。

function ParentComp () {
  // ....
  const [ name, setName ] = useState('hi~')
  const [ age, setAge ] = useState(20)
  const changeName = useCallback((newName) => setName(newName), [])
  const info = useMemo(() => ({ name, age }), [name, age])   // 包一層

  return (
    <div>
      <button onClick={increment}>點擊次數:{count}</button>
      <ChildComp info={info} onClick={changeName}/>
    </div>
  );
}

點擊父組件按鈕,控制臺中不再打印子組件被渲染的信息了。

五、useContext

React的useContext應用場景:如果需要在組件A、B之間共享狀態,可以使用useContext()。在它們的父組件上使用React的Context API,在組件外部建立一個Context。否則需要使用props一層層傳遞參數。

import React,{ useContext } from 'react'
const Ceshi = () => {
  const AppContext = React.createContext({})
  const A =() => {
    const { name } = useContext(AppContext)
    return (
        <p>A{name}</p>
    )
}
const B =() => {
  const { name } = useContext(AppContext)
  return (
      <p>B{name}</p>
  )
}
  return (
    <AppContext.Provider value={{name: 'hook測試'}}>
    <A/>
    <B/>
    </AppContext.Provider>
  )
}
export default Ceshi 

顯示:Ahook測試,Bhook測試

六、useRef

只能為類組件定義ref屬性,而不能為函數組件定義ref屬性。想要在函數式組件中使用Ref,我們必須先了解兩個Api,useRefforwardRef

1、返回一個可變的ref對象,該對象只有個current屬性,初始值為傳入的參數(initialValue)。
2、返回的ref對象在組件的整個生命周期內保持不變
3、當更新current值時并不會re-render,這是與useState不同的地方
4、更新useRef是side effect(副作用),所以一般寫在useEffect或event handler里
5、useRef類似于類組件的this
6、每個組件的 ref 只跟組件本身有關,跟其他組件的 ref 沒有關系
import React, { useRef } from 'react'
const LikeButton: React.FC = () => {
    let like = useRef(0)
    function handleAlertClick() {
        setTimeout(() => {
            alert(`you clicked on ${like.current}`)
        }, 3000)
    }
    return (
        <>
            <button
                onClick={() => {like.current = like.current + 1}}>{like.current}贊</button>
            <button onClick=handleAlertClick}>Alert</button>
        </>
    )
}
export default LikeButton

useRef與createRef的區別

組件依賴的props以及state狀態發生變更觸發更新時,createRef每次都會返回個新的引用;而useRef不會隨著組件的更新而重新創建。

let refFromCreateRef = createRef()

可以通過useRef傳入子組件,調用子組件的方法。

forwardRef:將ref父類的ref作為參數傳入函數式組件中

const FancyButton = React.forwardRef((props, ref) => (  
  <button ref={ref} className="FancyButton">    
    {props.children}
  </button>
));
// 可以直接獲取到button的DOM節點
const ref = React.useRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

useImperativeHandle在函數式組件中,用于定義暴露給父組件的ref方法,用來限制子組件對外暴露的信息。

只有useImperativeHandle第二個參數定義的屬性跟方法可以在父組件能夠獲取到。

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
//渲染 <FancyInput ref={inputRef} /> 的父組件
//可以調用 inputRef.current.focus()

參考:

https://www.jianshu.com/p/d600f749bb19

https://www.jianshu.com/p/014ee0ebe959

https://blog.csdn.net/u011705725/article/details/115634265

總結

以上是生活随笔為你收集整理的React hooks解析(useState、useEffect、userReducer、useCallback、useMemo、userContext、useRef)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。