天天看點

React核心 -- React-Hooks

React核心 -- React-Hooks

 大家好,我是小丞同學,一名大二的前端愛好者

這篇文章是學習 React-Redux 資料共享 的學習筆記

非常感謝你的閱讀,不對的地方歡迎指正

願你忠于自己,熱愛生活

hooks 存在的意義

hooks 之間的狀态是獨立的,有自己獨立的上下文,不會出現混淆狀态的情況

讓函數有了狀态管理

解決了 元件樹不直覺、類元件難維護、邏輯不易複用的問題

避免函數重複執行的副作用

應用場景

1.利用 hooks 取代生命周期函數

2.讓元件有了狀态

3.元件輔助函數

4.處理發送請求

5.存取資料

6.做好性能優化

hooks API

從 react 中引入

1. useState

給函數元件添加狀态

·初始化以及更新元件狀态

const [count, setCount] = React.useState(0)      

接收一個參數作為初始值,傳回一個數組:第一個是狀态變量,第二個是修改變量的函數

2. useEffect

副作用 hooks

·給沒有生命周期的元件,添加結束渲染的信号

注意:

·render 之後執行的 hooks

第一個參數接收一個函數,在元件更新的時候執行

第二個參數接收一個數組,用來表示需要追蹤的變量,依賴清單,隻有依賴更新的時候才會更新内容

第一個參數的傳回值,傳回一個函數,在 useEffect 執行之前,都會先執行裡面傳回的函數

一般用于添加銷毀事件,這樣就能保證隻添加一個

React.useEffect(() => {
    console.log('被調用了');
    return () => {
        console.log('我要被解除安裝了');
    }
}, [count])      

列印

React核心 -- React-Hooks

3. useLayoutEffect

和 useEffect 很類似

它的作用是:在 DOM 更新完成之後執行某個操作

·有 DOM 操作的副作用 hooks

·在 DOM 更新之後執行

執行時機在 useEffect 之前,其他都和 useEffect 都相同

useEffect 執行時機在 render 之後

useLayoutEffect 執行時機在 DOM 更新之後

4. useMemo

作用:讓元件中的函數跟随狀态更新

注意:優化函數元件中的功能函數

為了避免由于其他狀态更新導緻的目前函數的被迫執行

第一個參數接收一個函數,第二個參數為數組的依賴清單,傳回一個值

const getDoubleNum = useMemo(() => {
    console.log('ddd')
    return 2 * num
}, [num])      

5. useCallback

作用:跟随狀态更新執行

·隻有依賴項改變時才執行

·useMemo( () => fn, deps) 相當于 useCallback(fn, deps)

不同點:

1.useCallback 傳回的是一個函數,不再是值

2.useCallback 緩存的是一個函數,useMemo 緩存的是一個值,如果依賴不更新,傳回的永遠是緩存的那個函數

3.給子元件中傳遞 props 的時候,如果目前元件不更新,不會觸發子元件的重新渲染

6. useRef

作用:長久儲存資料

注意事項:

·傳回一個子元素索引,這個索引在整個生命周期中保持不變

·對象發生改變時,不通知,屬性變更不重新渲染

1.儲存一個值,在整個生命周期中維持不變

2.重新指派 ref.current 不會觸發重新渲染

3.相當于建立一個額外的容器來存儲資料,我們可以在外部拿到這個值

當我們通過正常的方式去擷取計時器的 id 是無法擷取的,需要通過 ref

useEffect(() => {
    ref.current = setInterval(() => {
        setNum(num => num + 1)
    }, 400)
}, [])
useEffect(() => {
    if (num > 10) {
        console.log('到十了');
        clearInterval(ref.current)
    }
}, [num])      

7. useContext

作用:帶着子元件渲染

·上層資料發生改變,肯定會觸發重新渲染

1.我們需要引入 useContext 和 createContext 兩個内容

2.通過 createContext 建立一個 Context 句柄

3.通過 Provider 确定資料共享範圍

4.通過 value 來分發資料

5.在子元件中,通過 useContext 來擷取資料

import React, { useContext, createContext } from 'react'
const Context = createContext(null)
export default function Hook() {
    const [num, setNum] = React.useState(1)

    return (
        <h1>
            這是一個函數元件 - {num}
        // 确定範圍
            <Context.Provider value={num}>
                <Item1 num={num} />
                <Item2 num={num} />
            </Context.Provider>
        </h1>
    )
}
function Item1() {
    const num = useContext(Context)
    return <div>子元件1  {num}</div>
}
function Item2() {
    const num = useContext(Context)
    return <div>子元件2 {num}</div>
}
      

8. useReducer

作用:去其他地方借資源

注意:函數元件的 Redux 的操作

1.建立資料倉庫 store 和管理者 reducer

2.通過 useReducer(store,dispatch) 來擷取 state 和 dispatch

const store = {
    num: 10
}
const reducer = (state, action) => {
    switch (action.type) {
        case "":
            return
        default:
            return
    }
}
    const [state, dispatch] = useReducer(reducer, store)      

通過 dispatch 去派發 action

9. 自定義 hooks

放在 utils 檔案夾中,以 use 開頭命名

例如:模拟資料請求的 Hooks

import React, { useState, useEffect } from "react";
function useLoadData() {
  const [num, setNum] = useState(1);
  useEffect(() => {
    setTimeout(() => {
      setNum(2);
    }, 1000);
  }, []);
  return [num, setNum];
}
export default useLoadData;      

減少代碼耦合

我們希望 reducer 能讓每個元件來使用,我們自己寫一個 hooks

自定義一個自己的 LocalReducer

import React, { useReducer } from "react";
const store = { num: 1210 };
const reducer = (state, action) => {
  switch (action.type) {
    case "num":
      return { ...state, num: action.num };
    default:
      return { ...state };
  }
};
function useLocalReducer() {
  const [state, dispatch] = useReducer(reducer, store);
  return [state, dispatch];
}
export default useLocalReducer;      

1.引入 react 和自己需要的 hook

2.建立自己的hook函數

3.傳回一個數組,數組中第一個内容是資料,第二個是修改資料的函數

4.暴露自定義 hook 函數出去

5.引入自己的業務元件

繼續閱讀