詳解React中函數(shù)式組件與類組件的不同
Function Component 與 Class Component 有何不同
文章核心觀點(diǎn):
- Function components capture the rendered values.函數(shù)式組件捕獲的是已經(jīng)被render的值
解釋一下:
請(qǐng)看代碼:
Class component
class ProfilePage extends React.Component {
showMessage = () => {
alert('Followed ' + this.props.user);
};
handleClick = () => {
setTimeout(this.showMessage, 3000);
};
render() {
return <button onClick={this.handleClick}>Follow</button>;
}
}Function Component
function ProfilePage(props) {
const showMessage = () => {
alert('Followed ' + props.user);
};
const handleClick = () => {
setTimeout(showMessage, 3000);
};
return (
<button onClick={handleClick}>Follow</button>
);
}
這里有bug:
點(diǎn)擊在Sophie的profile的時(shí)候,follow這個(gè)人,然后在三秒之內(nèi)快速切換到另一個(gè)頁(yè)面(dan)。Function彈出框的效果是follow sophie,class 彈出框 follow dan。
所以說(shuō),function 是我們想要的效果,但是class 不是我們想要的效果。
為什么會(huì)出現(xiàn)這種情況呢?
Class Component:
在Class Component中,this.props是通過(guò)類的實(shí)例來(lái)訪問(wèn)的,它指向組件的props。當(dāng)setTimeout中的this.showMessage函數(shù)被調(diào)用時(shí),它仍然引用了Class Component的實(shí)例,因此它可以訪問(wèn)最新的this.props,這是為什么你看到Class Component中的this.props.user是最新的值的原因。
Function Component:
在Function Component中,props是通過(guò)函數(shù)的參數(shù)傳遞的。當(dāng)setTimeout中的showMessage函數(shù)被調(diào)用時(shí),它只是一個(gè)普通的JavaScript函數(shù),沒(méi)有與Function Component的實(shí)例關(guān)聯(lián),因此它只能訪問(wèn)在函數(shù)定義時(shí)傳遞給它的props,而不是最新的props值。
React 文檔中描述的 props 不是不可變(Immutable) 數(shù)據(jù)嗎?什么是不可變數(shù)據(jù)?
React 中的 props 通常被描述為不可變(immutable)數(shù)據(jù),這意味著一旦 props 被傳遞給組件,它們不應(yīng)該在組件內(nèi)部被直接修改。這種不可變性有助于確保組件的可預(yù)測(cè)性和穩(wěn)定性,因?yàn)樗乐沽私M件在不知情的情況下更改外部傳遞的數(shù)據(jù)。
然而,有一點(diǎn)需要注意:props 對(duì)象本身是不可變的,但傳遞給 props 的值可能是可變的。如果你將一個(gè)可變對(duì)象(例如一個(gè)數(shù)組或?qū)ο螅┳鳛?props 傳遞給組件,那么這個(gè)對(duì)象的內(nèi)容可以在組件內(nèi)部被修改。這并不違反 React 的不可變性原則,因?yàn)?React 控制的是 props 對(duì)象的不可變性,而不控制傳遞給 props 的值的不可變性。
function ParentComponent() {
const mutableArray = [1, 2, 3];
return <ChildComponent items={mutableArray} />;
}在這種情況下,mutableArray 是一個(gè)可變的數(shù)組。如果在 ChildComponent 內(nèi)部修改了 items 數(shù)組,它將影響到原始數(shù)組。這并不是 React 的 props 不可變性引起的問(wèn)題,而是因?yàn)?JavaScript 中的對(duì)象和數(shù)組是引用類型。如果你希望在 ChildComponent 中不修改原始數(shù)組,可以在內(nèi)部創(chuàng)建副本來(lái)操作數(shù)據(jù),以保持原始數(shù)據(jù)的不可變性。
總之,React 中的 props 本身是不可變的,但你需要注意傳遞給 props 的值的可變性,特別是當(dāng)傳遞引用類型的值時(shí)。在組件內(nèi)部,始終確保遵循不可變性原則,以避免意外的副作用。
有沒(méi)有辦法解決這個(gè)問(wèn)題?
class ProfilePage extends React.Component {
render() {
// Capture the props!
const props = this.props;
// Note: we are *inside render*.
// These aren't class methods.
const showMessage = () => {
alert('Followed ' + props.user);
};
const handleClick = () => {
setTimeout(showMessage, 3000);
};
return <button onClick={handleClick}>Follow</button>;
}
}通過(guò)在 render 方法內(nèi)部創(chuàng)建一個(gè)局部變量 props 并將其設(shè)置為 this.props 的值,你捕獲了初始渲染時(shí)的 props 值。這意味著 props 變量將包含初始渲染時(shí)傳遞給組件的值,不受后續(xù)渲染的影響。
這種方法有時(shí)被用來(lái)解決在閉包函數(shù)(如 showMessage 和 handleClick 中的函數(shù))中訪問(wèn)最新 props 值的需求。由于在函數(shù)內(nèi)部,props 變量是一個(gè)常數(shù)(const),所以它將保持對(duì)初始 props 值的引用,不會(huì)隨后的渲染而改變。
那么我想在Function Component中,如何獲取到最新的數(shù)據(jù)?
使用React的useEffect鉤子,以依賴props的變化來(lái)執(zhí)行相應(yīng)的操作。這樣,當(dāng)props更新時(shí),useEffect內(nèi)的代碼會(huì)重新運(yùn)行,確保你獲取到最新的props值。
import { useEffect } from 'react';
function ProfilePage(props) {
useEffect(() => {
// 依賴props的變化,當(dāng)props更新時(shí),這里的代碼會(huì)重新運(yùn)行
console.log(props);
}, [props]);
}那么在異步的時(shí)候,為什么有捕獲到初始值的情況?
Function Components是純函數(shù),它們的行為在某種程度上類似于閉包。當(dāng)函數(shù)組件被創(chuàng)建時(shí),它會(huì)捕獲當(dāng)前的作用域(包括props和其他變量)。這意味著在函數(shù)組件內(nèi)部,函數(shù)參數(shù)(包括props)的值在組件的整個(gè)生命周期內(nèi)保持不變,即使父組件在此期間重新渲染了。
function MyComponent(props) {
const someValue = props.someProp;
setTimeout(() => {
console.log(someValue); // 這里的someValue是在組件初始渲染時(shí)捕獲的值
}, 3000);
}在這個(gè)示例中,someValue 變量在組件初始渲染時(shí)捕獲了 props.someProp 的值,即使在異步操作中訪問(wèn) someValue,它仍然保持不變,因?yàn)樗窃诤瘮?shù)作用域內(nèi)被捕獲的。
這就是為什么在Function Component中,在異步操作中可能會(huì)訪問(wèn)到初始的props值的原因。如果你希望在異步操作中訪問(wèn)最新的props值,你可以使用React的useEffect Hook來(lái)處理副作用,以依賴props的變化來(lái)執(zhí)行相應(yīng)的操作。這樣,當(dāng)props更新時(shí),useEffect內(nèi)的代碼會(huì)重新運(yùn)行,確保你獲取到最新的props值。
總結(jié):
1.class component 使用this 指向可以獲取到實(shí)例中最新的props值。function component 是個(gè)純函數(shù),相當(dāng)于閉包,捕獲的值就是當(dāng)前作用域的值。
2.如果function component想獲取到最新的值,可以使用hooks,如useEffect,來(lái)處理副作用,并在props變化時(shí)執(zhí)行相應(yīng)的操作,以確保獲取到最新的props值。
3.React 中props的不可變性,指的是不要在組件中對(duì)它進(jìn)行修改。所以使用function component純函數(shù)更好,結(jié)果值只與參數(shù)有關(guān),不會(huì)對(duì)外部產(chǎn)生副作用。
以上就是詳解React中函數(shù)式組件與類組件的不同的詳細(xì)內(nèi)容,更多關(guān)于React函數(shù)式組件與類組件的不同的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解析TypeError:import_react_native.AppState.removeEventListener
這篇文章主要為大家介紹了TypeError:import_react_native.AppState.removeEventListener?is?not?a?function問(wèn)題解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
react父組件更改props子組件無(wú)法刷新原因及解決方法
使用過(guò)vue的朋友都知道,vue父組件更改props的值,子組件是會(huì)刷新的,而react就未必,今天通過(guò)一個(gè)例子給大家介紹react父組件更改props子組件無(wú)法刷新原因,需要的朋友可以參考下2022-09-09
React基礎(chǔ)-JSX的本質(zhì)-虛擬DOM的創(chuàng)建過(guò)程實(shí)例分析
這篇文章主要介紹了React基礎(chǔ)-JSX的本質(zhì)-虛擬DOM的創(chuàng)建過(guò)程,結(jié)合具體實(shí)例形式分析了虛擬dom的基本原理與實(shí)現(xiàn)方法,需要的朋友可以參考下2023-05-05

