網站首頁 編程語言 正文
hooks是什么
hooks理解字面意思就是鉤子,是一些可以讓你在函數組件里鉤入 React state以及生命周期等特性的函數,可以讓不編寫class的情況下使用state以及其他的React特性
Hooks的作用
為函數組件提供狀態,生命周期等原本在class組件中才提供的功能
Hooks只能在函數組件中使用
可以理解為通過Hooks為函數組件鉤入class組件的特性
使用Hooks組件前后開發模式的對比
使用前(React v 16.8前):class組件(提供狀態)+函數組件(展示內容)
使用后(React v 16.8后):Hooks(提供狀態)+函數組件(展示內容)
Hooks使用策略
(1)react沒有計劃從React中移除class
(2)hook和現有代碼可以同時工作,可以漸進式使用
不推薦直接使用Hooks大規模重構現有組件
推薦新功能使用Hooks,復雜功能實現不來,也可以繼續使用class
(3)class組件相關的API在hooks里面可以不用
state setState 鉤子函數,this相關用法
(4)原來學習的內容還是要用
JSX:{} onClick={} 、條件渲染、列表渲染、樣式處理
組件:函數組件,組件通訊
react開發理念:單向數據流,狀態提升
為什么要有Hooks
首先我們要了解react的本質,接著從函數組件和類組件進行分析優缺點
react本質:用于構建用戶界面的javascript庫,是對特定功能的封裝,主要對url進行拆分
react組件的模型其實很直觀,就是從model到view的映射,這里的model對應的是react的state和props
函數式組件的好處:
- 函數本身比較簡單,更好的勝任根據狀態來渲染url這件事
- hooks讓函數組件內部有了維護狀態的能力
- hooks帶來了組件的邏輯復用的能力
class組件自身的問題:
- 在根據狀態來渲染url這件事上,class組件并沒有發揮它的重要功能
- 組件之間很少繼承
- 組件之間很少相互訪問
useState
作用:為函數組件提供state狀態
步驟:
- 導入useState函數
- 調用useState函數,傳入初始值,返回狀態和修改狀態的函數
- 使用:在jsx中展示狀態,特定的時機調用修改狀態的函數修改狀態
- 定義state數據,返回一個數組,有兩個值,第一個值,定義數據初始化的值,第二個值,修改數據函數,可以做到頁面的響應式
useState兩種格式:
格式1:傳入值 useState(0) 或useState('abc')
格式2:傳入回調,useState({上一次的值}=>{return 新值})
- 回調函數的返回值就是狀態的當前值
- 回調函數只會觸發一次
代碼展示
import React, { useState } from 'react'
export default function UseState() {
let [count,setCount]=useState(10)
// 他是異步的操作,在頁面數據會進行更新,但是下面打印的數據是沒有更新,原因是因為他是異步的
const plus=()=>{
setCount(count+5)
}
return (
<div>
{/* 函數組件中沒有this指向,我們可以直接調用 */}
<div>{count}</div>
<button onClick={()=>setCount(count++)}>加加</button>
<button onClick={plus}>plus</button>
</div>
)
}
注意:上面必須引入useState 使用
useEffect使用
函數式組件:
主作用:就是根據數據(state/props)渲染ul
副作用:數據請求,手動修改DOM、開啟定時器、清空定時器、localStorage操作等
副作用:只要是渲染數據之外的操作都是副作用,副作用不一定非要寫在useEffect里,可以寫外面,但是寫useEffect會起到約束作用
執行時機(以下兩種情況會執行Effect):
- 組件掛載時,執行一次(相當于生命周期中componentDidMount)
- 組件更新時,可能執行多次(相當于生命周期中的componentDidUpdate)
在實際開發中,副作用是不可避免的,react專門用useEffect來處理組件中的副作用
useEffect依賴項
有兩個參數:(參數一:(副作用函數),參數二:(執行副作用函數的依賴項,他決定了什么時候執行參數1(副作用)))
- 如果不設置第二個參數,那么每次頁面更新他都會執行
- 參數是空數組,永遠只執行第一次
- 指定依賴項,執行時機(初始化執行一次,依賴項發生變化執行一次)可以有多個依賴項
- useEffect() 代替三個生命周期函數 componentDidMount compoentDidUpdate 鉤子函數, componentWillUnmount 生命周期
使用情景
- 事件綁定
- 發送請求獲取數據等 axios ajax
useEffect(()=>{ 邏輯}) 頁面數據只要更新就會觸發useEffect()
useEffect(()=>{},[]) useEffect() 只執行一次,只有頁面第一次加載的時候觸發,componentDidMount
useEffect(()=>{}, [num,count]) 監聽數據改變執行,num和count發生變化的時候觸發。compoentDidUpdate
useEffect(()=>{
return ()=>{
console.log("相當于compoentDidUnmount")
}
},[])
//回調函數返回函數,返回的函數相當于銷毀生命周期函數。
useMemo使用
相當于vue中計算屬性,他一般需要返回一個結果,具有緩存性的效果
useMemo他是在DOM更新的時候觸發的,useEffect() DOM更新后觸發的副作用函數
緩存復雜運算的結果,避免重復調用執行
useMemo頁面一般會渲染第一次執行后的結果
代碼展示
import React, { useMemo, useState } from 'react'
export default function UseState() {
let [count,setCount]=useState(10)
// useMemo必須有返回值,而且他是在dom更新發生變化,比useEffect執行的快,useEffect是dom更新完才執行的,監聽count值變化
const double=useMemo(()=>{
console.log('useMemo觸發');
return count+6
},[count])
return (
<div>
{/* 函數組件中沒有this指向,我們可以直接調用 */}
<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對組件進行緩存,避免父組件中根子組件無關數據更新導致子組件的重新渲染。
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>子組件接受數據{props.count}</h3>
)
}
第二種通過react自帶的memo方法
memo是一個高階組件方法,接受一個組件作為參數,根據組件傳遞的參數值,對組件進行緩存,避免組件的多余的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對組件進行緩存,避免父組件中根子組件無關數據更新導致子組件的重新渲染。
const Theme = memo((props)=>{
useEffect(()=>{
console.log("子組件渲染")
});
return (
<h3>子組件接受數據{props.count}</h3>
)
})
useMemo和useEffect的區別
不同點:
useEffect是在dom更新后觸發的副作用函數,他被稱為副作用函數就是因為他在我們更新完成之后才通知我們,類似于馬后炮,useEffect不需要返回值,他沒有數據緩存的作用
useMemo是在dom更新時觸發的,useMemo必須要返回數據的結果,他是具有緩存數據的作用
共同點:
如果非要說共同點,那么他倆都有兩個參數,并且第二個參數如果是空[]的話,那么他的數據只會執行一次,也可以給他設置監聽項,[監聽值的名稱],第二個參數是可選參數,也可以不寫,不寫就是頁面只要發生一點改變,就會重新渲染一次,浪費數據更新的性能
useCallback使用
在上述的例子中如果我們傳遞的是普通的變量,緩存后,父組件更新的話不會導致子組件的更新,但是如果你傳遞的是一個函數,父組件的每次更新都會重新調用一次函數,這個時候就會不同函數調用,會導致子組件的重新渲染,如果我們還要做組件緩存,我們可以使用useCallback() , 可以對函數進行一個緩存的作用
代碼展示
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對組件進行緩存,避免父組件中根子組件無關數據更新導致子組件的重新渲染。
const Theme = memo((props)=>{
useEffect(()=>{
console.log("子組件渲染")
});
return (
<div>
<h3>子組件接受數據{props.count}</h3>
<button onClick={()=>props.handle()}>點擊</button>
</div>
)
})
useMemo,memo,useCallback如何提升性能的(面試題必問)?
useMemo主要的作用是緩存復雜運算的數據返回的結果,有兩個參數,第二個參數可以定義要監聽的數據,并且需要返回,跟useEffect第二個參數的作用類同
當父組件的組件更新的時候會導致子組件的重新渲染,但是如果父組件的更新的數據沒有傳遞給子組件的話,這時候還讓子組件重新渲染的話,會導致組件更新性能消耗比較大
所以說這個時候我們可以使用useMemo,或者使用react內置的memo方法對子組件進行緩存,這樣只有父組件更新跟子組件有關的數據時才會導致子組件重新渲染,從而提高組件的渲染性能
但是如果我們給子組件傳遞的是一個方法的時候,上面的useMemo,memo方法緩存就不起作用了,原因是父組件每更新一次會導致方法的重新調用,進而導致子組件的重新更新,這時候我們可以用到useCallback對傳遞的方法進行緩存,監聽數據更新后才會重新調用方法,從而提高組件的渲染性能
useContext使用
用來獲取context狀態樹的內容數據的Hooks的APi,相當于class組件中static contextType = react.createContext創建的對象內容
代碼展示
import React, { useContext, useState } from 'react';
//useContext用于獲取context狀態樹的值
// 首先創建一個空的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()的作用,用于創建ref節點對象的內容
//創建一個ref對象的內容
let inp = useRef(null);
const setVal =()=>{
console.log(inp.current.value);
}
<input placeholder='輸入內容' ref={inp} onChange={setVal}/>
為什么在函數組件中無法使用ref
普通的類組件有實例所以可以用React。createRef()掛載到節點或者組件上,然后通過this獲取到該節點或組件,正常情況下ref是不能掛到函數組件上,因為函數組件沒有實例
如何在類組件中使用ref屬性
我們可以通過forwardRef將ref父類的ref作為參數傳入函數式組件中
forwardRef是一個高階函數,跟memo一樣
還有一種方法就是把函數組件改成類組件
function Home() {
//定義一個初始化變量
let inpRef = useRef(null);
const getTheme = ()=>{
console.log(inpRef);
}
return (
<div>
<input placeholder='輸入內容'/>
<button onClick={getTheme}>獲取子組件對象</button>
<hr />
<Theme ref={inpRef}/>
</div>
)
}
const Theme = forwardRef(function(props,ref){
return (
<h3 ref={ref}>文字內容顯示</h3>
)
})
自定義hooks
寫一個自定義頁面標題的效果,路由中使用
import { useEffect } from "react";
//自定義顯示標題的Hooks的方法內容
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方法,這舉例的是一種
原文鏈接:https://blog.csdn.net/qq_60976312/article/details/125624109
相關推薦
- 2022-05-06 python?selenium中Excel數據維護指南_python
- 2022-07-03 nginx?緩存使用及配置步驟_nginx
- 2023-02-07 Pytorch中torch.argmax()函數使用及說明_python
- 2022-09-05 淺析Servlet三大容器的常用方法及其作用域
- 2022-09-15 C++如何計算二進制數中1的個數_C 語言
- 2022-11-15 一文詳解React?Redux使用方法_React
- 2022-11-29 Android?Jetpack組件DataBinding詳解_Android
- 2022-11-02 Python封裝解構以及丟棄變量_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支