React hooks的優(yōu)缺點(diǎn)詳解
前言
Hook 是 React 16.8 的新增特性。它是完全可選的,并且100%向后兼容。它可以讓你使用函數(shù)組件的方式,運(yùn)用類組件以及 react 其他的一些特性,比如管理狀態(tài)、生命周期鉤子等。從概念上講,React 組件一直更像是函數(shù)。而 Hook 則擁抱了函數(shù),同時(shí)也沒有犧牲 React 的精神原則。
優(yōu)點(diǎn):
1、代碼可讀性更強(qiáng),原本同一塊功能的代碼邏輯被拆分在了不同的生命周期函數(shù)中,容易使開發(fā)者不利于維護(hù)和迭代,通過 React Hooks 可以將功能代碼聚合,方便閱讀維護(hù)。例如,每個(gè)生命周期中常常會(huì)包含一些不相關(guān)的邏輯。一般我們都會(huì)在 componentDidMount 和 componentDidUpdate 中獲取數(shù)據(jù)。但是,同一個(gè) componentDidMount 中可能也包含很多其它的邏輯,如設(shè)置事件監(jiān)聽,而之后需在 componentWillUnmount 中清除。相互關(guān)聯(lián)且需要對(duì)照修改的代碼被進(jìn)行了拆分,而完全不相關(guān)的代碼卻在同一個(gè)方法中組合在一起。如此很容易產(chǎn)生 bug,并且導(dǎo)致邏輯不一致。
2、組件樹層級(jí)變淺。在原本的代碼中,我們經(jīng)常使用 HOC/render props 等方式來復(fù)用組件的狀態(tài),增強(qiáng)功能等,無疑增加了組件樹層數(shù)及渲染,在 React DevTools 中觀察過 React 應(yīng)用,你會(huì)發(fā)現(xiàn)由 providers,consumers,高階組件,render props 等其他抽象層組成的組件會(huì)形成“嵌套地獄”。而在 React Hooks 中,這些功能都可以通過強(qiáng)大的自定義的 Hooks 來實(shí)現(xiàn)。
3、不用再去考慮 this 的指向問題。在類組件中,你必須去理解 JavaScript 中 this 的工作方式。
缺點(diǎn):
一、響應(yīng)式的useEffect
寫函數(shù)組件時(shí),你不得不改變一些寫法習(xí)慣。你必須清楚代碼中useEffect和useCallback的“依賴項(xiàng)數(shù)組”的改變時(shí)機(jī)。有時(shí)候,你的useEffect依賴某個(gè)函數(shù)的不可變性,這個(gè)函數(shù)的不可變性又依賴于另一個(gè)函數(shù)的不可變性,這樣便形成了一條依賴鏈。一旦這條依賴鏈的某個(gè)節(jié)點(diǎn)意外地被改變了,你的useEffect就被意外地觸發(fā)了,如果你的useEffect是冪等的操作,可能帶來的是性能層次的問題,如果是非冪等,那就糟糕了。
所以,對(duì)比componentDidmount和componentDidUpdate,useEffect帶來的心智負(fù)擔(dān)更大。
二、狀態(tài)不同步
函數(shù)的運(yùn)行是獨(dú)立的,每個(gè)函數(shù)都有一份獨(dú)立的作用域。函數(shù)的變量是保存在運(yùn)行時(shí)的作用域里面,當(dāng)我們有異步操作的時(shí)候,經(jīng)常會(huì)碰到異步回調(diào)的變量引用是之前的,也就是舊的(這里也可以理解成閉包)。比如下面的一個(gè)例子:
import React, { useState } from "react";
const Counter = () => {
const [counter, setCounter] = useState(0);
const onAlertButtonClick = () => {
setTimeout(() => {
alert("Value: " + counter);
}, 3000);
};
return (
<div>
<p>You clicked {counter} times.</p>
<button onClick={() => setCounter(counter + 1)}>Click me</button>
<button onClick={onAlertButtonClick}>
Show me the value in 3 seconds
</button>
</div>
);
};
export default Counter;
當(dāng)你點(diǎn)擊Show me the value in 3 seconds的后,緊接著點(diǎn)擊Click me使得counter的值從0變成1。三秒后,定時(shí)器觸發(fā),但alert出來的是0(舊值),但我們希望的結(jié)果是當(dāng)前的狀態(tài)1。
這個(gè)問題在class component不會(huì)出現(xiàn),因?yàn)閏lass component的屬性和方法都存放在一個(gè)instance上,調(diào)用方式是:this.state.xxx和this.method()。因?yàn)槊看味际菑囊粋€(gè)不變的instance上進(jìn)行取值,所以不存在引用是舊的問題。
其實(shí)解決這個(gè)hooks的問題也可以參照類的instance。用useRef返回的immutable RefObject(current屬性是可變的)來保存state,然后取值方式從counter變成了: counterRef.current。如下:
import React, { useState, useRef, useEffect } from "react";
const Counter = () => {
const [counter, setCounter] = useState(0);
const counterRef = useRef(counter);
const onAlertButtonClick = () => {
setTimeout(() => {
alert("Value: " + counterRef.current);
}, 3000);
};
useEffect(() => {
counterRef.current = counter;
});
return (
<div>
<p>You clicked {counter} times.</p>
<button onClick={() => setCounter(counter + 1)}>Click me</button>
<button onClick={onAlertButtonClick}>
Show me the value in 3 seconds
</button>
</div>
);
};
export default Counter;
結(jié)果我們所期待,alert的是當(dāng)前的值1。
怎么避免react hooks的常見問題
- 不要在useEffect里面寫太多的依賴項(xiàng),劃分這些依賴項(xiàng)成多個(gè)單一功能的useEffect。其實(shí)這點(diǎn)是遵循了軟件設(shè)計(jì)的“單一職責(zé)模式”。
- 如果你碰到狀態(tài)不同步的問題,可以考慮下手動(dòng)傳遞參數(shù)到函數(shù)。如:
// showCount的count來自父級(jí)作用域
const [count,setCount] = useState(xxx);
function showCount(){ console.log(count) }
// showCount的count來自參數(shù)
const [count,setCount] = useState(xxx);
function showCount(c){ console.log(c) }
但這個(gè)也只能解決一部分問題,很多時(shí)候你不得不使用上述的useRef方案。
3. 重視eslint-plugin-react-hooks插件的警告。
4. 復(fù)雜業(yè)務(wù)的時(shí)候,使用Component代替hooks。
以上就是React hooks的優(yōu)缺點(diǎn)詳解的詳細(xì)內(nèi)容,更多關(guān)于React hooks的優(yōu)缺點(diǎn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于React Native使用axios進(jìn)行網(wǎng)絡(luò)請(qǐng)求的方法
axios是一個(gè)基于Promise的Http網(wǎng)絡(luò)庫,可運(yùn)行在瀏覽器端和Node.js中,Vue應(yīng)用的網(wǎng)絡(luò)請(qǐng)求基本都是使用它完成的。這篇文章主要介紹了React Native使用axios進(jìn)行網(wǎng)絡(luò)請(qǐng)求,需要的朋友可以參考下2021-08-08
react如何使用useRef模仿抖音標(biāo)題里面添加標(biāo)簽內(nèi)容
本文介紹了如何模仿抖音發(fā)布頁面,使用div元素作為輸入框,并利用CSS樣式和JavaScript動(dòng)態(tài)操作DOM,實(shí)現(xiàn)類似于input輸入框的功能,感興趣的朋友跟隨小編一起看看吧2024-10-10
ReactNative實(shí)現(xiàn)Toast的示例
這篇文章主要介紹了ReactNative實(shí)現(xiàn)Toast的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12
react+redux的升級(jí)版todoList的實(shí)現(xiàn)
本篇文章主要介紹了react+redux的升級(jí)版todoList的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12
ReactNative實(shí)現(xiàn)弧形拖動(dòng)條的代碼案例
本文介紹了ReactNative實(shí)現(xiàn)弧形拖動(dòng)條,本組件使用到了react-native-svg和PanResponder,結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-02-02
react滾動(dòng)加載useInfiniteScroll?詳解
使用useInfiniteScroll?hook可以處理檢測(cè)用戶何時(shí)滾動(dòng)到頁面底部的邏輯,并觸發(fā)回調(diào)函數(shù)以加載更多數(shù)據(jù),它還提供了一種簡(jiǎn)單的方法來管理加載和錯(cuò)誤消息的狀態(tài),今天通過實(shí)例代碼介紹下react滾動(dòng)加載useInfiniteScroll?相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧2023-09-09
ReactNative支付密碼輸入框?qū)崿F(xiàn)詳解
這篇文章主要為大家介紹了ReactNative支付密碼輸入框?qū)崿F(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
React router cache route實(shí)現(xiàn)緩存頁面流程介紹
react-router自身沒有路由緩存的特性,在5.x版本之前,我們可以基于react-router-cache-route來實(shí)現(xiàn)路由緩存功能。但是react-router 6.x在實(shí)現(xiàn)上做了比較大的變化,react-router-cache-route沒有提供相應(yīng)的支持2023-01-01
react 跳轉(zhuǎn)后路由變了頁面沒刷新的解決方案
最近在學(xué)習(xí)React的過程中遇到了路由跳轉(zhuǎn)后頁面不刷新的問題,本文就詳細(xì)的介紹一下解決方法,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06

