欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React-hooks面試考察知識點(diǎn)匯總小結(jié)(推薦)

 更新時間:2022年10月06日 09:31:22   作者:beifeng1996  
這篇文章主要介紹了React-hooks面試考察知識點(diǎn)匯總,Hook?使你在無需修改組件結(jié)構(gòu)的情況下復(fù)用狀態(tài)邏輯,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下

什么是hooks?解決了什么問題?

Hooks 是react16.8新增特性,它可以使用一些state的新特性,簡化邏輯復(fù)用,副作用統(tǒng)一數(shù)據(jù)。

Hooks就是把某個目標(biāo)結(jié)果鉤到某個可能會變化的數(shù)據(jù)源或者事件源上,那么當(dāng)被鉤到的數(shù)據(jù)或者事件發(fā)生變化時,產(chǎn)生這個目標(biāo)結(jié)果的代碼會重新執(zhí)行,產(chǎn)生更新后的結(jié)果。

Hook 簡介

Hook出世之前React存在的問題

  • 在組件之間復(fù)用狀態(tài)邏輯很難

    React 沒有提供將可復(fù)用性行為“附加”到組件的途徑(例如,把組件連接到 store)。有一些解決此類問題的方案,比如 render props 和 高階組件。但是這類方案需要重新組織你的組件結(jié)構(gòu),這可能會很麻煩,使你的代碼難以理解。

  • 復(fù)雜組件變得難以理解

    組件常常在 componentDidMount 和 componentDidUpdate中獲取數(shù)據(jù)。但是,同一個 componentDidMount 中可能也包含很多其它的邏輯,如設(shè)置事件監(jiān)聽,而之后需在 componentWillUnmount 中清除。相互關(guān)聯(lián)且需要對照修改的代碼被進(jìn)行了拆分,而完全不相關(guān)的代碼卻在同一個方法中組合在一起。如此很容易產(chǎn)生 bug,并且導(dǎo)致邏輯不一致。

  • 難以理解的 class

    class 是學(xué)習(xí) React 的一大屏障。你必須去理解 JavaScript 中 this 的工作方式,這與其他語言存在巨大差異。還不能忘記綁定事件處理器。沒有穩(wěn)定的語法提案,這些代碼非常冗余。大家可以很好地理解 props,state 和自頂向下的數(shù)據(jù)流,但對 class 卻一籌莫展。

Hook帶來的解決方案

  • 你可以使用 Hook 從組件中提取狀態(tài)邏輯,使得這些邏輯可以單獨(dú)測試并復(fù)用。Hook 使你在無需修改組件結(jié)構(gòu)的情況下復(fù)用狀態(tài)邏輯。
  • Hook 將組件中相互關(guān)聯(lián)的部分拆分成更小的函數(shù)(比如設(shè)置訂閱或請求數(shù)據(jù)),而并非強(qiáng)制按照生命周期劃分。你還可以使用 reducer 來管理組件的內(nèi)部狀態(tài),使其更加可預(yù)測。
  • Hook 使你在非 class 的情況下可以使用更多的 React 特性。 從概念上講,React 組件一直更像是函數(shù)。而 Hook 則擁抱了函數(shù),同時也沒有犧牲 React 的精神原則。Hook 提供了問題的解決方案,無需學(xué)習(xí)復(fù)雜的函數(shù)式或響應(yīng)式編程技術(shù)。

Hook API

useState

useState 是react自帶的一個hook函數(shù),它的作用就是用來聲明狀態(tài)變量。useState這個函數(shù)接收的參數(shù)是我們的狀態(tài)初始值(initial state),它返回了一個數(shù)組,這個數(shù)組的第[0]項是當(dāng)前當(dāng)前的狀態(tài)值,第[1]項是可以改變狀態(tài)值的方法函數(shù)。

初始化

//返回一個 state,以及更新 state 的函數(shù) setState(接收一個新的 state 值并將組件的一次重新渲染加入隊列)
const [state, setState] = useState(initialState);

函數(shù)式更新

//如果新的 state 需要通過使用先前的 state 計算得出,那么可以將函數(shù)傳遞給 setState。該函數(shù)將接收先前的 state,并返回一個更新后的值。
function Counter({initialCount}) {
  const [count, setCount] = useState(initialCount);
  return (
    <>
      Count: {count}      <button onClick={() => setCount(initialCount)}>Reset</button>
      <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
      <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
    </>
  );
}

惰性初始 state

//如果初始 state 需要通過復(fù)雜計算獲得,則可以傳入一個函數(shù),在函數(shù)中計算并返回初始的 state,此函數(shù)只在初始渲染時被調(diào)用
const [state, setState] = useState(() => {
  const initialState = someExpensiveComputation(props);
  return initialState;
});

跳過 state 更新

調(diào)用 State Hook 的更新函數(shù)并傳入當(dāng)前的 state 時,React 將跳過子組件的渲染及 effect 的執(zhí)行。(React 使用 Object.is 比較算法 來比較 state。)

useEffect

我們寫的有狀態(tài)組件,通常會產(chǎn)生很多的副作用(side effect),比如發(fā)起ajax請求獲取數(shù)據(jù),添加一些監(jiān)聽的注冊和取消注冊,手動修改dom等等。我們之前都把這些副作用的函數(shù)寫在生命周期函數(shù)鉤子里,比如componentDidMount,componentDidUpdatecomponentWillUnmount。而現(xiàn)在的useEffect就相當(dāng)與這些聲明周期函數(shù)鉤子的集合體。它以一抵三。

簡單例子

import { useState, useEffect } from 'react';

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

  // 類似于componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    // 更新文檔的標(biāo)題
    document.title = `You clicked ${count} times`;
  });

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

清除 effect

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

useEffect(() => {
  const subscription = props.source.subscribe();
  return () => {
    // 清除訂閱
    subscription.unsubscribe();
  };
});

為防止內(nèi)存泄漏,清除函數(shù)會在組件卸載前執(zhí)行。另外,如果組件多次渲染(通常如此),則在執(zhí)行下一個 effect 之前,上一個 effect 就已被清除。

effect 的執(zhí)行時機(jī)

componentDidMount、componentDidUpdate 不同的是,在瀏覽器完成布局與繪制之后,傳給 useEffect 的函數(shù)會延遲調(diào)用。這使得它適用于許多常見的副作用場景,比如設(shè)置訂閱和事件處理等情況,因此不應(yīng)在函數(shù)中執(zhí)行阻塞瀏覽器更新屏幕的操作。

effect 的條件執(zhí)行

默認(rèn)情況下,effect 會在每輪組件渲染完成后執(zhí)行。這樣的話,一旦 effect 的依賴發(fā)生變化,它就會被重新創(chuàng)建。在某些情況下,我們不需要在每次組件更新時都創(chuàng)建新的訂閱,而是僅需要在 source prop 改變時重新創(chuàng)建。要實現(xiàn)這一點(diǎn),可以給 useEffect 傳遞第二個參數(shù),它是 effect 所依賴的值數(shù)組。

//此時,只有當(dāng) props.source 改變后才會重新創(chuàng)建訂閱。(要實現(xiàn)componentDidMount功能只需要設(shè)置第二個參數(shù)為[]即可)
useEffect(
  () => {
    const subscription = props.source.subscribe();
    return () => {
      subscription.unsubscribe();
    };
  },
  [props.source],
);

useContext

可以深層組件傳值,父組件傳給子孫組件。接收一個 context 對象(React.createContext 的返回值)并返回該 context 的當(dāng)前值。當(dāng)前的 context 值由上層組件中距離當(dāng)前組件最近的 <MyContext.Provider>value prop 決定。

當(dāng)組件上層最近的 <MyContext.Provider> 更新時,該 Hook 會觸發(fā)重渲染,并使用最新傳遞給 MyContext provider 的 context value 值。即使祖先使用 React.memoshouldComponentUpdate,也會在組件本身使用 useContext 時重新渲染

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!    </button>
  );
}

useReducer

useState 的替代方案,可以用于復(fù)雜狀態(tài)處理。它接收一個形如 (state, action) => newState 的 reducer,并返回當(dāng)前的 state 以及與其配套的 dispatch 方法。(如果你熟悉 Redux 的話,就已經(jīng)知道它如何工作了。)參考 前端react面試題詳細(xì)解答

指定初始 state

有兩種不同初始化 useReducer state 的方式,你可以根據(jù)使用場景選擇其中的一種。將初始 state 作為第二個參數(shù)傳入 useReducer 是最簡單的方法:

//nst [state, dispatch] = useReducer(reducer, initialArg, init);
 const [state, dispatch] = useReducer(
    reducer,
    {count: initialCount}
 );

某些場景下,useReducer 會比 useState 更適用,例如 state 邏輯較復(fù)雜且包含多個子值,或者下一個 state 依賴于之前的 state 等。并且,使用 useReducer 還能給那些會觸發(fā)深更新的組件做性能優(yōu)化,因為你可以向子組件傳遞 dispatch 而不是回調(diào)函數(shù) 。

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

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

惰性初始化

你可以選擇惰性地創(chuàng)建初始 state。為此,需要將 init 函數(shù)作為 useReducer 的第三個參數(shù)傳入,這樣初始 state 將被設(shè)置為 init(initialArg)。

這么做可以將用于計算 state 的邏輯提取到 reducer 外部,這也為將來對重置 state 的 action 做處理提供了便利:

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

跳過 dispatch

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

useMemo

把“創(chuàng)建”函數(shù)和依賴項數(shù)組作為參數(shù)傳入 useMemo,它僅會在某個依賴項改變時才重新計算 memoized 值。這種優(yōu)化有助于避免在每次渲染時都進(jìn)行高開銷的計算。如果沒有提供依賴項數(shù)組,useMemo 在每次渲染時都會計算新的值。memo是淺比較,意思是,對象只比較內(nèi)存地址,只要你內(nèi)存地址沒變,管你對象里面的值千變?nèi)f化都不會觸發(fā)render。

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

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

useCallback

把內(nèi)聯(lián)回調(diào)函數(shù)及依賴項數(shù)組作為參數(shù)傳入 useCallback,它將返回該回調(diào)函數(shù)的 memoized 版本,該回調(diào)函數(shù)僅在某個依賴項改變時才會更新。當(dāng)你把回調(diào)函數(shù)傳遞給經(jīng)過優(yōu)化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子組件時,它將非常有用。

useMemouseCallback 類似,都是有著緩存的作用,useMemo 是緩存值的,useCallback 是緩存函數(shù)的。

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

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useRef

useRef 返回一個可變的 ref 對象,其 .current 屬性被初始化為傳入的參數(shù)(initialValue)。返回的 ref 對象在組件的整個生命周期內(nèi)保持不變。

useEffect里面的state的值,是固定的,這個是有辦法解決的,就是用useRef,可以理解成useRef的一個作用:就是相當(dāng)于全局作用域,一處被修改,其他地方全更新。

本質(zhì)上,useRef 就像是可以在其 .current 屬性中保存一個可變值的“盒子”。你應(yīng)該熟悉 ref 這一種訪問 DOM 的主要方式。如果你將 ref 對象以 <div ref={myRef} /> 形式傳入組件,則無論該節(jié)點(diǎn)如何改變,React 都會將 ref 對象的 .current 屬性設(shè)置為相應(yīng)的 DOM 節(jié)點(diǎn)。然而,useRef()ref 屬性更有用。它可以很方便地保存任何可變值,其類似于在 class 中使用實例字段的方式。

請記住,當(dāng) ref 對象內(nèi)容發(fā)生變化時,useRef 并不會通知你。變更 .current 屬性不會引發(fā)組件重新渲染。如果想要在 React 綁定或解綁 DOM 節(jié)點(diǎn)的 ref 時運(yùn)行某些代碼,則需要使用回調(diào) ref 來實現(xiàn)。

const Hook =()=>{
    const [count, setCount] = useState(0)
    const btnRef = useRef(null)

    useEffect(() => {
        console.log('use effect...')
        const onClick = ()=>{
            setCount(count+1)
        }
        btnRef.current.addEventListener('click',onClick, false)
        return ()=> btnRef.current.removeEventListener('click',onClick, false)
    },[count])

    return(
        <div>
            <div>
                {count}            </div>
            <button ref={btnRef}>click me </button>
        </div>
    )
}

useImperativeHandle

useImperativeHandle(ref, createHandle, [deps])

useImperativeHandle 可以讓你在使用 ref 時自定義暴露給父組件的實例值。在大多數(shù)情況下,應(yīng)當(dāng)避免使用 ref 這樣的命令式代碼。useImperativeHandle 應(yīng)當(dāng)與 forwardRef 一起使用:

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

在本例中,渲染 <FancyInput ref={inputRef} /> 的父組件可以調(diào)用 inputRef.current.focus()。

自定義 Hook

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

例如,下面的 useFriendStatus 是我們第一個自定義的 Hook:

import { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

自定義一個當(dāng)resize 的時候 監(jiān)聽window的width和height的hook

import {useEffect, useState} from "react";

export const useWindowSize = () => {
    const [width, setWidth] = useState()
    const [height, setHeight] = useState()

    useEffect(() => {
        const {clientWidth, clientHeight} = document.documentElement
        setWidth(clientWidth)
        setHeight(clientHeight)
    }, [])

    useEffect(() => {
        const handleWindowSize = () =>{
            const {clientWidth, clientHeight} = document.documentElement
            setWidth(clientWidth)
            setHeight(clientHeight)
        };

        window.addEventListener('resize', handleWindowSize, false)

        return () => {
            window.removeEventListener('resize',handleWindowSize, false)
        }
    })

    return [width, height]
}

使用:

const [width, height] = useWindowSize()
const isOnline = useFriendStatus(id);

 

到此這篇關(guān)于React-hooks面試考察知識點(diǎn)匯總的文章就介紹到這了,更多相關(guān)React-hooks面試內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 在React項目中使用iframe嵌入一個網(wǎng)站的步驟

    在React項目中使用iframe嵌入一個網(wǎng)站的步驟

    本文介紹了如何在React項目中通過iframe嵌入百度網(wǎng)站的步驟,首先創(chuàng)建一個Baidu.js組件,并在該組件中設(shè)置iframe來加載百度,然后在App.js中引入并使用Baidu組件,還討論了因安全策略可能無法加載某些網(wǎng)站的問題,需要的朋友可以參考下
    2024-09-09
  • 基于React實現(xiàn)搜索GitHub用戶功能

    基于React實現(xiàn)搜索GitHub用戶功能

    在本篇博客中,我們將介紹如何在 React 應(yīng)用中搜索 GitHub 用戶并顯示他們的信息,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • reset.css瀏覽器默認(rèn)樣式表重置(user?agent?stylesheet)的示例代碼

    reset.css瀏覽器默認(rèn)樣式表重置(user?agent?stylesheet)的示例代碼

    這篇文章主要介紹了reset.css瀏覽器默認(rèn)樣式表重置(user?agent?stylesheet),本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-12-12
  • Ant?Design?組件庫之步驟條實現(xiàn)

    Ant?Design?組件庫之步驟條實現(xiàn)

    這篇文章主要為大家介紹了Ant?Design組件庫之步驟條實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • react?hooks?UI與業(yè)務(wù)邏輯分離必要性技術(shù)方案

    react?hooks?UI與業(yè)務(wù)邏輯分離必要性技術(shù)方案

    這篇文章主要為大家介紹了react?hooks?UI與業(yè)務(wù)邏輯分離必要性技術(shù)方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • React實現(xiàn)下拉框的key,value的值同時傳送

    React實現(xiàn)下拉框的key,value的值同時傳送

    這篇文章主要介紹了React實現(xiàn)下拉框的key,value的值同時傳送方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • 使用React.forwardRef傳遞泛型參數(shù)

    使用React.forwardRef傳遞泛型參數(shù)

    這篇文章主要介紹了使用React.forwardRef傳遞泛型參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • react中axios結(jié)合后端實現(xiàn)GET和POST請求方式

    react中axios結(jié)合后端實現(xiàn)GET和POST請求方式

    這篇文章主要介紹了react中axios結(jié)合后端實現(xiàn)GET和POST請求方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 淺談React和Redux的連接react-redux

    淺談React和Redux的連接react-redux

    本篇文章主要介紹了淺談React和Redux的連接react-redux,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • react實現(xiàn)Modal彈窗效果

    react實現(xiàn)Modal彈窗效果

    這篇文章主要為大家詳細(xì)介紹了react實現(xiàn)Modal彈窗效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08

最新評論