日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

React Hook基本使用踩坑指南

發(fā)布時間:2025/4/16 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 React Hook基本使用踩坑指南 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

React因為提倡函數(shù)式編程,所以提出了Hook思想來增強函數(shù)組件的功能,以此來替代基于Class的組件。但是我們有可能從基于Class這樣的實例化組件轉(zhuǎn)向函數(shù)組件時思想還沒有完全轉(zhuǎn)過來,還是用基于實例的思想考慮問題,忘記了函數(shù)有用完即銷毀(特別是純函數(shù))這樣的特點,導(dǎo)致在使用React Hook的時候可能會出一些問題。下面的內(nèi)容就來記錄一下,使用React Hook的新手可能會遇到的一些問題。


Hook使用原則

首先要強調(diào)一下Hook的使用原則,可以參考我之前寫的文章:如何使用React Hook最后的部分,也可以參考一下官網(wǎng)。遵守Hook使用原則,可以幫助你在使用Hook時避免很多問題。


useState數(shù)據(jù)只能通過setState來修改

我們舉一個代碼的例子:

import React, { useState } from 'react'// 子組件 function Child({ userInfo }) {// render: 初始化 state// re-render: 只恢復(fù)初始化的 state 值,不會再重新設(shè)置新的值// 只能用 setName 修改const [ name, setName ] = useState(userInfo.name)return <div><p>Child, props name: {userInfo.name}</p><p>Child, state name: {name}</p></div> }function App() {const [name, setName] = useState('中國')const userInfo = { name }return <div><div>Parent &nbsp;<button onClick={() => setName('美國')}>setName</button></div><Child userInfo={userInfo}/></div> }export default App

這里有一個簡單的父子組件的例子,實現(xiàn)效果大概是這樣的:

當(dāng)我們點擊setName按鈕之后,結(jié)果變成這樣:

你可能會覺得很奇怪,我明明把父組件的數(shù)據(jù)傳遞給子組件了,但是我子組件的數(shù)據(jù)為什么還是中國而不是美國呢?

這是useState的一個規(guī)則,就是state值得更新,只能通過setState來去做,這是一條鐵律,即使父組件的值修改也不能改變子組件的值,要想修改子組件的值只能通過setState來去修改。

你可能又會有一個新的疑惑,函數(shù)組件不是執(zhí)行完之后就銷毀了嗎,re-render的時候,子組件怎么能記住之前的值呢?這是因為React內(nèi)部有一個記憶機制,會按順序記住之前函數(shù)組件的值。所以我們在使用Hook的時候一定不要在循環(huán),條件或嵌套函數(shù)中調(diào)用 Hook,因為只要有條件判斷,state在re-render重新賦值的時候,值就可能發(fā)生錯亂(React只能保證按順序賦值),導(dǎo)致最后輸出結(jié)果不符合預(yù)期。


useEffect修改state時本身狀態(tài)對結(jié)果影響

舉一下代碼的例子:

function UseEffectChangeState() {const [count, setCount] = useState(0)// 模擬 DidMountuseEffect(() => {console.log('useEffect...', count)// 定時任務(wù)const timer = setInterval(() => {console.log('setInterval...', count)// setCount(count + 1)setCount(count+1)}, 1000)// 清除定時任務(wù)return () => clearTimeout(timer)}, []) // 依賴為 []// 依賴為 [] 時: re-render 不會重新執(zhí)行 effect 函數(shù)// 沒有依賴:re-render 會重新執(zhí)行 effect 函數(shù)return <div>count: {count}</div> }export default UseEffectChangeState

這是一個很簡單的定時任務(wù),我們希望使用useEffect來實現(xiàn)DidMount是添加一個定時器并每秒更新一下count的值。然而顯示結(jié)果卻是這樣的:

可以看到,我們的期望落空了,count值始終是1,即使間隔100多秒也沒有發(fā)生任何變化。我們之前明明說,可以通過setState來修改值,這里也的確是用了setState,可是為什么結(jié)果沒有達到預(yù)期呢?

因為如果useEffect是DidMount狀態(tài)話,re-render的時候是不會重新執(zhí)行useEffect的,也就是setState沒有執(zhí)行,所以count始終是1。如果useEffect有DidUpdate狀態(tài)的話,re-render的時候,就會重新執(zhí)行useEffect,那樣的話,count的值是會發(fā)生變化,符合我們預(yù)期。


useEffect使用引用類型可能會發(fā)生死循環(huán)

在講解這個問題之前首先要理解一個概念:基本類型和引用類型,如果對這個概念不太清楚地話,可以參考我之前寫的一篇文章:通俗易懂講解JavaScript深拷貝和淺拷貝

我們再來看一段代碼,這段代碼和第二部分的useEffect的代碼基本一致:

function UseEffectChangeState() {const [count, setCount] = useState(0)// 模擬 DidMountuseEffect(() => {console.log('useEffect...', count)// 定時任務(wù)const timer = setInterval(() => {console.log('setInterval...', count)// setCount(count + 1)setCount(count+1)}, 1000)// 清除定時任務(wù)return () => clearTimeout(timer)}, [{}]) // 依賴為 [] 時: re-render 不會重新執(zhí)行 effect 函數(shù)// 沒有依賴:re-render 會重新執(zhí)行 effect 函數(shù)return <div>count: {count}</div> }export default UseEffectChangeState

只是有一個地方不同,就是useEffect最后不是[]而改變成[{}]。我們在學(xué)習(xí)Hook文檔時,它舉的更新監(jiān)聽數(shù)值,使用useEffect實現(xiàn)update功能的例子都是使用的值類型(或者叫基本類型),如果我們使用引用類型(對象、數(shù)組)會怎么樣呢?

運行代碼你會發(fā)現(xiàn),count值居然也更新了,而沒有出現(xiàn)第二部分剛開始的那種情況(即count值始終保持為1),這就有問題啊,我沒有監(jiān)聽count,但它也更新,這代碼不符合預(yù)期。

為什么會出現(xiàn)這種情況呢?是因為react監(jiān)聽值發(fā)生變化,那如何判斷數(shù)值的確是發(fā)生變化了呢?它使用的是Object.is()的方式。你可以執(zhí)行一下看看:

Object.is('foo', 'foo'); // true Object.is('foo', 'bar'); // falseObject.is([], []); // false Object.is({}, {}); // false

對于引用類型的話,它始終都是false,判斷機制失效了,所以就會一直更新。所以我們在使用useEffect更新的時候,一定要使用基本類型,而不要使用引用類型。


參考資料

[1] 如何使用React Hook

總結(jié)

以上是生活随笔為你收集整理的React Hook基本使用踩坑指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。