React Hooks 學(xué)習(xí)總結(jié)

前言

最近的換寫React項目了,好久沒有寫React酒甸,還動不動就想class??堆巧,現(xiàn)在跟上時代礁叔,重新學(xué)習(xí)React Hook.Hook 是 React 16.8 的新增特性牍颈。它可以讓你在不編寫 class 的情況下使用 state 以及其他的 React 特性。

為什么有Hook琅关?

1煮岁、在組件之間復(fù)用狀態(tài)邏輯比較難,需要用到高階組件或者render props死姚,Hook可以無需修改組件結(jié)構(gòu)的情況下人乓,復(fù)用狀態(tài)邏輯。
2都毒、Hook可以將組件中相互關(guān)聯(lián)的部分拆分成更小的函數(shù)色罚,方便理解;
3账劲、不再使用class和this戳护,更方便上手和理解;

使用Hook的注意事項

1瀑焦、只能在最外層函數(shù)中調(diào)用Hook腌且。(不要在循環(huán)、條件判斷榛瓮、子函數(shù)中調(diào)用)
React在創(chuàng)建hook時铺董,以鏈表的解構(gòu)存儲,前一個hook中next指針指向下一個hook禀晓。在組件更新時會進行hook的一一對應(yīng)的比對精续,所以要保證每次hook數(shù)量一致,位置相同粹懒。循環(huán)重付、條件判斷中使用hook,會導(dǎo)致數(shù)量和位置的變化凫乖,產(chǎn)生錯誤确垫。
2弓颈、只在react的函數(shù)組件中調(diào)用。

常用的HooK

1.useState

  • 作用:在組件內(nèi)部添加一個state删掀,React會在重復(fù)渲染時保留這個state翔冀。
  • 參數(shù): 1個,state的初始值initialState爬迟;
const [state,setState] =useState(initialState)
  • 返回值 :2個
    1)state 當(dāng)前狀態(tài)橘蜜,在初始渲染時菊匿,state就是initialState
    2)setState更新當(dāng)前state的函數(shù)付呕,他接受一個新的state,并且將該組件的一次渲染加入隊列跌捆,他有點類似類組件中this.setState,但并不會將新舊state合并
//在函數(shù)組件中
const [state,setState] =useState({name:"lily",age:18})
return(
<button onclick={setState({age:20})}>改變年齡<button>
//這里使用useState不會將新舊state徽职,現(xiàn)在state為{age:20},name屬性就沒有了
//所以需要注意 onclick={setState({...state,age:20})}
)
  • 特點
    1) 每次渲染都是獨立的閉包佩厚,擁有當(dāng)前自己的props\state\函數(shù)
    2)函數(shù)式更新
//如果新的狀態(tài)需要依賴舊的狀態(tài)姆钉,可以使用函數(shù)式更新
setState(state =>({...state,age:state.age +1}))
//將舊狀態(tài)傳入,返回新的狀態(tài)

3)懶加載初始化state

//如果state中的值需要復(fù)雜計算
const [state,setState] =useState(()=>  ({name:"lily",age:12}))
  • 性能優(yōu)化(減少渲染次數(shù))
    1)Object.is
    在調(diào)用state的更新函數(shù)時抄瓦,React會先進行Object.is的比較算法
    如果state不相同潮瓶,進行子組件渲染和effect,否則不進行刷新渲染

2)useMemo(緩存值)
某些情況下組件中的值需要依賴state進行計算后得到钙姊,由于每次組件更新都會去重新計算毯辅,為了減少性能消耗,可以使用useMemo緩存值煞额,僅僅當(dāng)依賴改變時,才重新計算。

  • 參數(shù):計算函數(shù)嗜暴,依賴數(shù)組
    則函數(shù)僅會在某個依賴項改變時才重新計算memoized 值绰更。
 const [count, setCount] = useState(0);
//expensive 需要依賴count計算得到
 const expensive = useMemo(() => {
 let sum = 0;
 for (let i = 0; i < count; i++) {
 sum += i;
 }
 return sum;
 //只有count變化,這?才重新執(zhí)?
 }, [count]);

3)useCallback (緩存回調(diào)函數(shù))
由于每次組件更新都會內(nèi)部函數(shù)都會重新創(chuàng)建一次婚温,為了節(jié)省性能描焰,可以使用useCallback,使內(nèi)聯(lián)回調(diào)函數(shù)僅僅在傳入依賴項改變時進行更新栅螟。

  • 參數(shù):內(nèi)聯(lián)回調(diào)函數(shù)荆秦,依賴數(shù)組
    則函數(shù)僅會在某個依賴項改變時才進行更新。
 const [count, setCount] = useState(0);
 const addClick = useCallback(() => {
setCount(count+1)
 }, [count]);

4)memo (緩存組件)
父組件更新子組件也會重新創(chuàng)建嵌巷,為節(jié)省性能萄凤,可用memo將子組件緩存,僅僅當(dāng)props改變時搪哪,組件才進行更新

const Child = (props)=>{
return <div>{props.age}</div>
}
//這里只會在props改變的時候重新渲染
Child =memo(Child)
const Father=()=>{
const [name,setName]=useState("lily")
const [age,setAge]=useState(18)
return(
<>
<button onclick={setAge(age+1)}>改變年齡<button>
<input onChange={e=>(setName(e.target.value))}>改變姓名<button>
<Child age={age}/> 
</>
)
}

5)useRef (緩存ref)
同理靡努,用useRef可對React.creactRef對象進緩存

2. useReducer

  • 作用:編寫自定義hook或者在某些改變state邏輯復(fù)雜的情況下替代useState,用法類似redux,useState是useReducer的語法糖惑朦。
  • 參數(shù): 3個兽泄,reducer方法 、initialState初始值漾月,init病梢;
const [state,dispatch] =useReducer(reducer ,initialState)
  • 返回值 :2個
    1)state當(dāng)前狀態(tài)梁肿,在初始渲染時蜓陌,state就是initialState
    2)dispatch派發(fā)方法,接受參數(shù)action吩蔑,改變當(dāng)前state钮热,并且將該組件的一次渲染加人隊列。

  • 自定義hook

//實現(xiàn)一個useState
const useState=(initalState)=>{
    const reducer = useCallback(_state,action)=>{
        return action.paylaod
    }
    const [state,dispatch] = useReducer(reducer, initalState)
    const setState = (state)=>{
        dispatch({paylaod:state})
    }
    return [state,setState]
}

3.useContext

  • 作用:提供更方便的方法從React上下文中拿到consumer的值
    參數(shù): 1個烛芬,context(React.createContext)隧期;
const  value=useContext(context)
  • 返回值 :1個 consumer的值

4.useEffect

  • 作用:在React渲染階段,改變DOM赘娄、添加訂閱仆潮、設(shè)置定時器等操作會破壞UI一致性,含有副作用的操作將不被允許遣臼,使用useEffect完成副作用的操作性置,傳入函數(shù)會在組件渲染后執(zhí)行.
  • 參數(shù): 2個,didUpdate包含副作用的回調(diào)函數(shù)暑诸,在組件渲染后執(zhí)行,[state]依賴項蚌讼,傳入依賴項,僅在依賴項改變后的執(zhí)行
useEffect(didUpdate,[state])
  • 返回值 :1個 清除副作用函數(shù)个榕,在組件銷毀前執(zhí)行篡石,相當(dāng)于componentWillUnmount,可進行定時器西采,事件監(jiān)聽的移除操作
  • 特點
    由于useEffect的副作用函數(shù)在組件渲染后執(zhí)行凰萨,他和class組件中的 生命周期componentDidMount/componentDidUpdate和componentWillUnmount有相同的用途

5.useRef、useImperativeHandle

  • useRef作用:對ref對象進緩存械馆,ref 對象在組件的整個生命周期內(nèi)保持不變胖眷。
  • 參數(shù): 1個,initialValue霹崎,ref.curren初始化的值
function  FocusButton() {
    const inputEl = useRef(null); 
    const onButtonClick = () => {
        // `current` 指向已掛載到 DOM 上的文本輸入元素
        inputEl.current.focus();
    };
    return (
        <>
            <input ref={inputEl} type="text" />
            <button onClick={onButtonClick}>Focus the input</button>
        </>
    );
}

  • useImperativeHandle作用:有些情況下我們需要父組件把ref傳遞給子組件珊搀,僅僅使用forwardRef將子組件的ref屬性都暴露給父組件是危險的,也違反了封裝原則尾菇,useImperativeHandle允許在子組件中把自定義實例附加到父組件傳過來的ref上境析,減少暴露給父組件的屬性
  • 參數(shù): 3個囚枪,ref, createHandle處理函數(shù),其返回值會替換父組件傳來的ref.current, [state]依賴項
useImperativeHandle(ref, createHandle, [state])
  • 例子
let Child =  (props, ref) =>{
    const inputRef = useRef();
    useImperativeHandle(ref, () => ({
        focus: () => {
            inputRef.current.focus()
        }
    }));
    return <input ref={inputRef} />;
}
Child = forwardRef(Child );

const Father=() => {
    const ref = useRef(null);
    return (
        <>
            <Child ref={ref}/>
             <button onClick={()=>{ ref.current.focus()}}>聚焦</button >
        </>
    )
}

6.useLayoutEffect

  • 作用 :與useEffect相同劳淆,都是用來執(zhí)行副作用链沼。
  • 特點 :useEffect是在渲染之后調(diào)用effect,也就是下一楨執(zhí)行沛鸵,是異步的括勺;
    而useLayoutEffect在當(dāng)前幀Render tree計算布局(Layout)信息后,渲染前曲掰,同步調(diào)用effect疾捍。官方文檔建議使用標(biāo)準(zhǔn)useEffec。

7.自定義Hook

  • 定義:函數(shù)以use開頭并且在函數(shù)內(nèi)部調(diào)用其他hooks蜈缤,并且返回一個數(shù)組拾氓,可以實現(xiàn)邏輯復(fù)用冯挎。
  • 例子 :
//實現(xiàn)一個thunk
const useThunk =(reducer,initalState)=>{
const [state,dispatch] =useReducer(reducer,initalState)
const thunkDispatch = (action)=>{
if( action instanceof Function){ //如果action是函數(shù)底哥,傳入新的dispatch執(zhí)行action
   return action (thunkDispatch,()=>state)
}else{
dispatch(action )
}
return [state,thunkDispatch]
}


結(jié)尾

現(xiàn)在就只了解到這么多。還有什么沒寫到的日后更新房官。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末趾徽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子翰守,更是在濱河造成了極大的恐慌孵奶,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜡峰,死亡現(xiàn)場離奇詭異了袁,居然都是意外死亡,警方通過查閱死者的電腦和手機湿颅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門载绿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人油航,你說我怎么就攤上這事崭庸。” “怎么了谊囚?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵怕享,是天一觀的道長。 經(jīng)常有香客問我镰踏,道長函筋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任奠伪,我火速辦了婚禮跌帐,結(jié)果婚禮上灌诅,老公的妹妹穿的比我還像新娘。我一直安慰自己含末,他們只是感情好猜拾,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著佣盒,像睡著了一般挎袜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肥惭,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天盯仪,我揣著相機與錄音,去河邊找鬼蜜葱。 笑死全景,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的牵囤。 我是一名探鬼主播爸黄,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼揭鳞!你這毒婦竟也來了炕贵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤野崇,失蹤者是張志新(化名)和其女友劉穎称开,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乓梨,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡鳖轰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了扶镀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蕴侣。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狈惫,靈堂內(nèi)的尸體忽然破棺而出睛蛛,到底是詐尸還是另有隱情,我是刑警寧澤胧谈,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布忆肾,位于F島的核電站,受9級特大地震影響菱肖,放射性物質(zhì)發(fā)生泄漏客冈。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一稳强、第九天 我趴在偏房一處隱蔽的房頂上張望场仲。 院中可真熱鬧和悦,春花似錦、人聲如沸渠缕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亦鳞。三九已至馍忽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間燕差,已是汗流浹背遭笋。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留徒探,地道東北人瓦呼。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像测暗,于是被迫代替她去往敵國和親央串。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353