Hook API

文章參考: Hook API 索引

普通Hook(常用)

useState、useEffect

useContext

前言:在一個典型的 React 應用中,數(shù)據(jù)是通過 props 屬性自上而下(由父及子)進行傳遞的,但這種做法對于某些類型的屬性而言是極其繁瑣的(例如:地區(qū)偏好,UI 主題),這些屬性是應用程序中許多組件都需要的。Context 提供了一種在組件之間共享此類值的方式,而不必顯式地通過組件樹的逐層傳遞 props。

創(chuàng)建一個Context對象,設置一個默認值Tom

const ThemeContext = React.createContext('Tom');

獲取Context對象的內(nèi)容,會向上找 Context.Provider的值

const theme = useContext(ThemeContext);

把如下代碼與 Context.Provider 放在一起

// Context 可以讓我們無須明確地傳遍每一個組件,就能將值深入傳遞進組件樹。
// 為當前的 theme 創(chuàng)建一個 context(“Tom”為默認值)。
const ThemeContext = React.createContext('Tom');
function App () {
    // 使用一個 Provider 來將當前的 theme 傳遞給以下的組件樹。
    // 無論多深,任何組件都能讀取這個值。
    // 在這個例子中,我們將 “Jerry” 作為當前的值傳遞下去。
    return (
      <ThemeContext.Provider value="Jerry">
        <Toolbar />
      </ThemeContext.Provider>
    );
}

// 中間的組件再也不必指明往下傳遞 theme 了。
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton () {
  // 指定 contextType 讀取當前的 theme context。
  // React 會往上找到最近的 theme Provider,然后使用它的值。
  // 在這個例子中,當前的 theme 值為 “Jerry”。
  const theme = useContext(ThemeContext);
  render() {
    return <Button theme={theme} />;
  }
}

其他Hook (不常用)

useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);

useState的替代方案。在state 邏輯較復雜且包含多個子值,或者下一個 state 依賴于之前的 state的情況下,useReducer 會比 useState 更適用

  • reducer
    它接收一個形如(state, action) => newState 的 reducer函數(shù),參數(shù)是當前的state值(state),和操作配置(action),最后返回一個新的state值
  • initialArg
    state的初始值
  • init
    這是一個可選值,可以用來惰性提供初始狀態(tài)。這意味著我們可以使用使用一個 init 函數(shù)來計算初始狀態(tài)/值,而不是顯式的提供值。如果初始值可能會不一樣,這會很方便,最后會用計算的值來代替初始值。

實現(xiàn)一個計數(shù)器

// 對初始值進行處理
function init(initialCount) {
    return {count: initialCount};
}
// reducer函數(shù),根據(jù)action配置處理state值
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>
    </>
  );
}

【注】跳過 dispatch
如果 Reducer Hook 的返回值與當前 state 相同,React 將跳過子組件的渲染及副作用的執(zhí)行。(React 使用 Object.is 比較算法)

useReducer源碼解釋

// state的處理配置
function todosReducer(state, action) {
  switch (action.type) {
    case 'add':
      return [...state, {
        text: action.text,
        completed: false
      }];
    // ... other actions ...
    default:
      return state;
  }
}
// useReducer源碼
function useReducer(reducer, initialState) {
  const [state, setState] = useState(initialState); // 設置staste,傳入初始值

  function dispatch(action) {    // useReaducer的第二個返回值,參數(shù)是state的配置對象
    const nextState = reducer(state, action);  //  調(diào)用傳入的state處理函數(shù),傳入state的初始值和配置,返回經(jīng)過處理的后的state值
    setState(nextState);  // 更新state值
  }

  return [state, dispatch]; // 返回設置的state值,和更新state的回調(diào)函數(shù)
}

const [todos, dispatch] = useReducer(todosReducer, []);

useCallback

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

useMemo

返回一個 memoized 值。(memoization的技巧在于將計算過的結(jié)果『緩存』下來,避免重復計算帶來的成本)

把“創(chuàng)建”函數(shù)和依賴項數(shù)組作為參數(shù)傳入 useMemo,它僅會在某個依賴項改變時才重新計算 memoized 值。這種優(yōu)化有助于避免在每次渲染時都進行高開銷的計算。

傳入 useMemo 的函數(shù)會在渲染期間執(zhí)行。請不要在這個函數(shù)內(nèi)部執(zhí)行與渲染無關的操作,諸如副作用這類的操作屬于 useEffect 的適用范疇,而不是 useMemo。

如果沒有提供依賴項數(shù)組,useMemo 在每次渲染時都會計算新的值。

你可以把 useMemo 作為性能優(yōu)化的手段,但不要把它當成語義上的保證。將來,React 可能會選擇“遺忘”以前的一些 memoized 值,并在下次渲染時重新計算它們,比如為離屏組件釋放內(nèi)存。先編寫在沒有 useMemo 的情況下也可以執(zhí)行的代碼 —— 之后再在你的代碼中添加 useMemo,以達到優(yōu)化性能的目的。

useRef

useRef返回一個可變的 ref 對象
一個常見的用例便是命令式地訪問子組件:

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>
    </>
  );
}

返回的ref對象,掛載到節(jié)點上,對象的指向就會變成該節(jié)點

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • Hooks是 React v16.8 的新特性,可以在不使用類組件的情況下,使用 state 以及其他的React...
    hellomyshadow閱讀 13,676評論 0 5
  • 最新在學ReactHooks這個新特性,把學習筆記記下來,供大家分享。 原先的函數(shù)組件是沒有生命周期函數(shù)的,這樣在...
    番茄_tomatoMan閱讀 1,830評論 0 0
  • 現(xiàn)在編寫新的組件的時候我們有兩個選擇:class組件和函數(shù)組件。那么什么是函數(shù)組件呢? 現(xiàn)在來看一段函數(shù): 可以看...
    arial_1df2閱讀 395評論 0 0
  • Hook 是 React 16.8 的新增特性。它可以讓你在不編寫 class 的情況下使用 state 以及其他...
    孤獨的小色狼閱讀 406評論 0 0
  • 使用React Hooks有什么優(yōu)勢? 什么是hookshook 是一些可以讓你在函數(shù)組件里面鉤入react st...
    Lyan_2ab3閱讀 398評論 0 1

友情鏈接更多精彩內(nèi)容