React?Hooks鉤子中API的使用示例分析
hooks是什么
hooks理解字面意思就是鉤子,是一些可以讓你在函數(shù)組件里鉤入 React state以及生命周期等特性的函數(shù),可以讓不編寫class的情況下使用state以及其他的React特性
Hooks的作用
為函數(shù)組件提供狀態(tài),生命周期等原本在class組件中才提供的功能
Hooks只能在函數(shù)組件中使用
可以理解為通過Hooks為函數(shù)組件鉤入class組件的特性
使用Hooks組件前后開發(fā)模式的對比
使用前(React v 16.8前):class組件(提供狀態(tài))+函數(shù)組件(展示內(nèi)容)
使用后(React v 16.8后):Hooks(提供狀態(tài))+函數(shù)組件(展示內(nèi)容)
Hooks使用策略
(1)react沒有計劃從React中移除class
(2)hook和現(xiàn)有代碼可以同時工作,可以漸進式使用
不推薦直接使用Hooks大規(guī)模重構(gòu)現(xiàn)有組件
推薦新功能使用Hooks,復(fù)雜功能實現(xiàn)不來,也可以繼續(xù)使用class
(3)class組件相關(guān)的API在hooks里面可以不用
state setState 鉤子函數(shù),this相關(guān)用法
(4)原來學(xué)習(xí)的內(nèi)容還是要用
JSX:{} onClick={} 、條件渲染、列表渲染、樣式處理
組件:函數(shù)組件,組件通訊
react開發(fā)理念:單向數(shù)據(jù)流,狀態(tài)提升
為什么要有Hooks
首先我們要了解react的本質(zhì),接著從函數(shù)組件和類組件進行分析優(yōu)缺點
react本質(zhì):用于構(gòu)建用戶界面的javascript庫,是對特定功能的封裝,主要對url進行拆分
react組件的模型其實很直觀,就是從model到view的映射,這里的model對應(yīng)的是react的state和props
函數(shù)式組件的好處:
- 函數(shù)本身比較簡單,更好的勝任根據(jù)狀態(tài)來渲染url這件事
- hooks讓函數(shù)組件內(nèi)部有了維護狀態(tài)的能力
- hooks帶來了組件的邏輯復(fù)用的能力
class組件自身的問題:
- 在根據(jù)狀態(tài)來渲染url這件事上,class組件并沒有發(fā)揮它的重要功能
- 組件之間很少繼承
- 組件之間很少相互訪問
useState
作用:為函數(shù)組件提供state狀態(tài)
步驟:
- 導(dǎo)入useState函數(shù)
- 調(diào)用useState函數(shù),傳入初始值,返回狀態(tài)和修改狀態(tài)的函數(shù)
- 使用:在jsx中展示狀態(tài),特定的時機調(diào)用修改狀態(tài)的函數(shù)修改狀態(tài)
- 定義state數(shù)據(jù),返回一個數(shù)組,有兩個值,第一個值,定義數(shù)據(jù)初始化的值,第二個值,修改數(shù)據(jù)函數(shù),可以做到頁面的響應(yīng)式
useState兩種格式:
格式1:傳入值 useState(0) 或useState('abc')
格式2:傳入回調(diào),useState({上一次的值}=>{return 新值})
- 回調(diào)函數(shù)的返回值就是狀態(tài)的當前值
- 回調(diào)函數(shù)只會觸發(fā)一次
代碼展示
import React, { useState } from 'react' export default function UseState() { let [count,setCount]=useState(10) // 他是異步的操作,在頁面數(shù)據(jù)會進行更新,但是下面打印的數(shù)據(jù)是沒有更新,原因是因為他是異步的 const plus=()=>{ setCount(count+5) } return ( <div> {/* 函數(shù)組件中沒有this指向,我們可以直接調(diào)用 */} <div>{count}</div> <button onClick={()=>setCount(count++)}>加加</button> <button onClick={plus}>plus</button> </div> ) }
注意:上面必須引入useState 使用
useEffect使用
函數(shù)式組件:
主作用:就是根據(jù)數(shù)據(jù)(state/props)渲染ul
副作用:數(shù)據(jù)請求,手動修改DOM、開啟定時器、清空定時器、localStorage操作等
副作用:只要是渲染數(shù)據(jù)之外的操作都是副作用,副作用不一定非要寫在useEffect里,可以寫外面,但是寫useEffect會起到約束作用
執(zhí)行時機(以下兩種情況會執(zhí)行Effect):
- 組件掛載時,執(zhí)行一次(相當于生命周期中componentDidMount)
- 組件更新時,可能執(zhí)行多次(相當于生命周期中的componentDidUpdate)
在實際開發(fā)中,副作用是不可避免的,react專門用useEffect來處理組件中的副作用
useEffect依賴項
有兩個參數(shù):(參數(shù)一:(副作用函數(shù)),參數(shù)二:(執(zhí)行副作用函數(shù)的依賴項,他決定了什么時候執(zhí)行參數(shù)1(副作用)))
- 如果不設(shè)置第二個參數(shù),那么每次頁面更新他都會執(zhí)行
- 參數(shù)是空數(shù)組,永遠只執(zhí)行第一次
- 指定依賴項,執(zhí)行時機(初始化執(zhí)行一次,依賴項發(fā)生變化執(zhí)行一次)可以有多個依賴項
- useEffect() 代替三個生命周期函數(shù) componentDidMount compoentDidUpdate 鉤子函數(shù), componentWillUnmount 生命周期
使用情景
- 事件綁定
- 發(fā)送請求獲取數(shù)據(jù)等 axios ajax
useEffect(()=>{ 邏輯}) 頁面數(shù)據(jù)只要更新就會觸發(fā)useEffect() useEffect(()=>{},[]) useEffect() 只執(zhí)行一次,只有頁面第一次加載的時候觸發(fā),componentDidMount useEffect(()=>{}, [num,count]) 監(jiān)聽數(shù)據(jù)改變執(zhí)行,num和count發(fā)生變化的時候觸發(fā)。compoentDidUpdate useEffect(()=>{ return ()=>{ console.log("相當于compoentDidUnmount") } },[]) //回調(diào)函數(shù)返回函數(shù),返回的函數(shù)相當于銷毀生命周期函數(shù)。
useMemo使用
相當于vue中計算屬性,他一般需要返回一個結(jié)果,具有緩存性的效果
useMemo他是在DOM更新的時候觸發(fā)的,useEffect() DOM更新后觸發(fā)的副作用函數(shù)
緩存復(fù)雜運算的結(jié)果,避免重復(fù)調(diào)用執(zhí)行
useMemo頁面一般會渲染第一次執(zhí)行后的結(jié)果
代碼展示
import React, { useMemo, useState } from 'react' export default function UseState() { let [count,setCount]=useState(10) // useMemo必須有返回值,而且他是在dom更新發(fā)生變化,比useEffect執(zhí)行的快,useEffect是dom更新完才執(zhí)行的,監(jiān)聽count值變化 const double=useMemo(()=>{ console.log('useMemo觸發(fā)'); return count+6 },[count]) return ( <div> {/* 函數(shù)組件中沒有this指向,我們可以直接調(diào)用 */} <div>{count} {double}</div> <button onClick={()=>setCount(count*2)}>count二倍</button> </div> ) }
useMemo緩存組件方式
第一種通過useMemo緩存組件
//useMemoe緩存組件 function Home() { let [count,setcount] = useState(10) let [num,setnum] = useState(20) //通過useMemoe對組件進行緩存,避免父組件中根子組件無關(guān)數(shù)據(jù)更新導(dǎo)致子組件的重新渲染。 let theme = useMemo(()=>{ return ( <Theme count={count}></Theme> ) },[count]) return ( <div> <h3 >count--{count}</h3> <button onClick={()=>setcount(count+1)}>count++</button> <h3 >num--{num}</h3> <button onClick={()=>setnum(num+1)}>num++</button> <hr /> {theme} </div> ) } function Theme(props){ useEffect(()=>{ console.log("子組件渲染") }); return ( <h3>子組件接受數(shù)據(jù){props.count}</h3> ) }
第二種通過react自帶的memo方法
memo是一個高階組件方法,接受一個組件作為參數(shù),根據(jù)組件傳遞的參數(shù)值,對組件進行緩存,避免組件的多余的DOM渲染效果
function Home() { let [count,setcount] = useState(10) let [num,setnum] = useState(20) return ( <div> <h3 >count--{count}</h3> <button onClick={()=>setcount(count+1)}>count++</button> <h3 >num--{num}</h3> <button onClick={()=>setnum(num+1)}>num++</button> <hr /> <Theme count={count}></Theme> </div> ) } //通過memo對組件進行緩存,避免父組件中根子組件無關(guān)數(shù)據(jù)更新導(dǎo)致子組件的重新渲染。 const Theme = memo((props)=>{ useEffect(()=>{ console.log("子組件渲染") }); return ( <h3>子組件接受數(shù)據(jù){props.count}</h3> ) })
useMemo和useEffect的區(qū)別
不同點:
useEffect是在dom更新后觸發(fā)的副作用函數(shù),他被稱為副作用函數(shù)就是因為他在我們更新完成之后才通知我們,類似于馬后炮,useEffect不需要返回值,他沒有數(shù)據(jù)緩存的作用
useMemo是在dom更新時觸發(fā)的,useMemo必須要返回數(shù)據(jù)的結(jié)果,他是具有緩存數(shù)據(jù)的作用
共同點:
如果非要說共同點,那么他倆都有兩個參數(shù),并且第二個參數(shù)如果是空[]的話,那么他的數(shù)據(jù)只會執(zhí)行一次,也可以給他設(shè)置監(jiān)聽項,[監(jiān)聽值的名稱],第二個參數(shù)是可選參數(shù),也可以不寫,不寫就是頁面只要發(fā)生一點改變,就會重新渲染一次,浪費數(shù)據(jù)更新的性能
useCallback使用
在上述的例子中如果我們傳遞的是普通的變量,緩存后,父組件更新的話不會導(dǎo)致子組件的更新,但是如果你傳遞的是一個函數(shù),父組件的每次更新都會重新調(diào)用一次函數(shù),這個時候就會不同函數(shù)調(diào)用,會導(dǎo)致子組件的重新渲染,如果我們還要做組件緩存,我們可以使用useCallback() , 可以對函數(shù)進行一個緩存的作用
代碼展示
function Home() { let [count,setcount] = useState(10) let [num,setnum] = useState(20) const handlerCount = ()=>{ console.log(count); } const callback = useCallback(()=>{ handlerCount(); },[count]); return ( <div> <h3 >count--{count}</h3> <button onClick={()=>setcount(count+1)}>count++</button> <h3 >num--{num}</h3> <button onClick={()=>setnum(num+1)}>num++</button> <hr /> <Theme count={count} handle={callback}></Theme> </div> ) } //通過memo對組件進行緩存,避免父組件中根子組件無關(guān)數(shù)據(jù)更新導(dǎo)致子組件的重新渲染。 const Theme = memo((props)=>{ useEffect(()=>{ console.log("子組件渲染") }); return ( <div> <h3>子組件接受數(shù)據(jù){props.count}</h3> <button onClick={()=>props.handle()}>點擊</button> </div> ) })
useMemo,memo,useCallback如何提升性能的(面試題必問)?
useMemo主要的作用是緩存復(fù)雜運算的數(shù)據(jù)返回的結(jié)果,有兩個參數(shù),第二個參數(shù)可以定義要監(jiān)聽的數(shù)據(jù),并且需要返回,跟useEffect第二個參數(shù)的作用類同
當父組件的組件更新的時候會導(dǎo)致子組件的重新渲染,但是如果父組件的更新的數(shù)據(jù)沒有傳遞給子組件的話,這時候還讓子組件重新渲染的話,會導(dǎo)致組件更新性能消耗比較大
所以說這個時候我們可以使用useMemo,或者使用react內(nèi)置的memo方法對子組件進行緩存,這樣只有父組件更新跟子組件有關(guān)的數(shù)據(jù)時才會導(dǎo)致子組件重新渲染,從而提高組件的渲染性能
但是如果我們給子組件傳遞的是一個方法的時候,上面的useMemo,memo方法緩存就不起作用了,原因是父組件每更新一次會導(dǎo)致方法的重新調(diào)用,進而導(dǎo)致子組件的重新更新,這時候我們可以用到useCallback對傳遞的方法進行緩存,監(jiān)聽數(shù)據(jù)更新后才會重新調(diào)用方法,從而提高組件的渲染性能
useContext使用
用來獲取context狀態(tài)樹的內(nèi)容數(shù)據(jù)的Hooks的APi,相當于class組件中static contextType = react.createContext創(chuàng)建的對象內(nèi)容
代碼展示
import React, { useContext, useState } from 'react'; //useContext用于獲取context狀態(tài)樹的值 // 首先創(chuàng)建一個空的context對象 const ThemContext =React.createContext(); function UseState() { let [color,setColor]=useState('#ff0000') return ( <div> {/* 通過Provider傳過來一個value值,是一個對象 */} <ThemContext.Provider value={{color:color}}> <button onClick={()=>setColor('pink')}>粉色</button> <button onClick={()=>setColor('blue')}>藍色</button> <button onClick={()=>setColor('green')}>綠色</button> <Son></Son> </ThemContext.Provider> </div> ) } // 子組件 function Son(props) { // 通過useContext獲取父組件傳過來的值 const context=useContext(ThemContext) return ( <div> {/* 然后對他進行樣式綁定 */} <h3 style={context}>hello,react</h3> </div> ) } export default UseState
useRef使用
useRef 作用相當于class組件React.createRef()的作用,用于創(chuàng)建ref節(jié)點對象的內(nèi)容
//創(chuàng)建一個ref對象的內(nèi)容 let inp = useRef(null); const setVal =()=>{ console.log(inp.current.value); } <input placeholder='輸入內(nèi)容' ref={inp} onChange={setVal}/>
為什么在函數(shù)組件中無法使用ref
普通的類組件有實例所以可以用React。createRef()掛載到節(jié)點或者組件上,然后通過this獲取到該節(jié)點或組件,正常情況下ref是不能掛到函數(shù)組件上,因為函數(shù)組件沒有實例
如何在類組件中使用ref屬性
我們可以通過forwardRef將ref父類的ref作為參數(shù)傳入函數(shù)式組件中
forwardRef是一個高階函數(shù),跟memo一樣
還有一種方法就是把函數(shù)組件改成類組件
function Home() { //定義一個初始化變量 let inpRef = useRef(null); const getTheme = ()=>{ console.log(inpRef); } return ( <div> <input placeholder='輸入內(nèi)容'/> <button onClick={getTheme}>獲取子組件對象</button> <hr /> <Theme ref={inpRef}/> </div> ) } const Theme = forwardRef(function(props,ref){ return ( <h3 ref={ref}>文字內(nèi)容顯示</h3> ) })
自定義hooks
寫一個自定義頁面標題的效果,路由中使用
import { useEffect } from "react"; //自定義顯示標題的Hooks的方法內(nèi)容 const useTitle = (title) => { useEffect(() => { document.title = title; return ()=>{ document.title="React 頁面" } }, []); return; } export { useTitle };
import { useTitle } from "../context/hooksApi" export default function My(){ useTitle("個人中心") return ( <div> <h3>個人中心</h3> </div> ) }
還有其他的自定義hooks API方法,這舉例的是一種
到此這篇關(guān)于React Hooks鉤子中API的使用示例分析I的文章就介紹到這了,更多相關(guān)React Hooks API內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React實現(xiàn)下拉框的key,value的值同時傳送
這篇文章主要介紹了React實現(xiàn)下拉框的key,value的值同時傳送方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08