發(fā)布于:2021-02-04 11:15:20
0
188
0
在許多情況下,React組件將在不必重新渲染時重新渲染。
如果渲染的結(jié)果與組件上一次渲染的結(jié)果完全相同,則最好完全跳過該渲染(協(xié)調(diào))步驟。
基于類的組件
shouldComponentUpdate
在類組件中,方法shouldComponentUpdate
允許這樣做。
它是在render()
之前調(diào)用的生命周期方法。該方法返回一個布爾值。如果render()
可以跳過,這個布爾值告訴React。
當(dāng)true
時,render()
將像平常一樣執(zhí)行。
當(dāng)false
時,告訴React它可以跳過執(zhí)行render()
。
用下一個道具和下一個狀態(tài)調(diào)用 默認情況下, 完全不指定此方法。 shouldComponentUpdate(nextProps, nextState) { 不要依賴于此來完全阻止渲染。它現(xiàn)在可能工作,但它可能會導(dǎo)致錯誤,并可能在未來發(fā)生變化。相反,將其視為一個反應(yīng)提示,告訴它“您可以安全地跳過渲染,結(jié)果將與上一個結(jié)果相同”。 在您知道之前,該方法看起來會是這樣的。 shouldComponentUpdate(nextProps, nextState) { 我只是想看看有沒有什么道具或者狀態(tài)改變了,為什么這么難? 這會減少跳過必要更新的可能性(例如,添加新道具時)。 除非您確信需要自定義道具,否則最好選擇 這意味著這兩個片段是等價的。 class Driver extends React.Component { 當(dāng)試圖將同樣的優(yōu)化應(yīng)用于函數(shù)組件而不是基于類的組件時,問題就出現(xiàn)了。函數(shù)組件不能真正跳過渲染步驟。函數(shù)組件(實際上只是一個函數(shù))要么執(zhí)行要么不執(zhí)行 這就是備忘錄有幫助的地方。 備忘錄基本上是一種技術(shù),用于以后記住一些東西。 React不能只記住數(shù)據(jù)片段,它可以記住整個組件。 前兩個示例是針對基于類的組件的, 不像在基于類的組件中那樣跳過渲染步驟, // the function component 帶有道具的記憶驅(qū)動程序組件的初始呈現(xiàn) 函數(shù)組件render <p>Charles Leclerc</p>。 道具更改為 組件渲染 <p>Daniel Ricciardo</p> 觸發(fā)驅(qū)動程序更新的其他更改組件 React使用前面的結(jié)果而不是計算渲染結(jié)果:<p>Daniel Ricciardo</p> 默認情況下, 比較函數(shù)還返回一個布爾值。 該布爾值告訴React它是否應(yīng)該使用組件的前一個結(jié)果,而不是計算新的結(jié)果。 當(dāng) 當(dāng) 小心!這與 使用上一個道具和下一個道具調(diào)用比較函數(shù)。這允許復(fù)雜的邏輯,將當(dāng)前道具與以前的道具進行比較,以確定輸出是否不同,因此應(yīng)使用組件的記憶結(jié)果/備忘錄。 // the function component 要使用基于類的組件擴展并行程序: 除非您確信需要自定義比較函數(shù),否則最好使用默認行為。 示例 在這個演示中,有一個頂級組件有兩個狀態(tài),一個是 您可以通過按鈕增加 頂部組件有4個子組件,所有子組件都將顯示 只有在更新 而 const memoizedValue = React.useMemo(() => computeExpensiveValue(a, b), [a, b]); 告訴 傳遞的函數(shù)中使用的每個值都應(yīng)包含在依賴項數(shù)組中。 這將防止許多意外行為。 React團隊創(chuàng)建了一個ESLint包, 示例 import React from 'react'; 使用props的驅(qū)動程序組件的初始呈現(xiàn) 函數(shù)組件計算 props更改為 React.useMemo看不到依賴項數(shù)組中的任何內(nèi)容已更改,并且不會重新計算numOfPodiums 使用 道具再次更改為 React.useMemo 看到依賴項數(shù)組中發(fā)生了一些變化并計算 numOfPodiums 并使用新計算的值。 這是特定 但值完全可以是函數(shù)! 這意味著這兩個片段是等價。 const memoizedFunction = React.useMemo(function() { 這將記憶第一個參數(shù)(函數(shù))返回的值,該值是一個名為 const memoizedFunction = React.useCallback(function doTheThing(a, b) { 這將記憶第一個參數(shù),這是一個名為 與 函數(shù)shouldComponentUpdate()
。這允許復(fù)雜的邏輯,將當(dāng)前的屬性/狀態(tài)與以前的屬性/狀態(tài)進行比較,以確定輸出是否不同,因此組件應(yīng)該更新。shouldComponentUpdate()
返回true。
return true
}shouldComponentUpdate
中的邏輯很快就會變得非常復(fù)雜,并且容易出錯。
const propsComparison = this.props.a !== nextProps.a && this.props.b !== nextProps.b && this.props.c !== nextProps.c && this.props.d !== nextProps.d
const stateComparison = this.state.one !== nextState.one && this.state.two !== nextState.two && this.state.three !== nextState.three
return propsComparison && stateComparison
}React.PureComponent
React.PureComponent
就是這樣!PureComponent
執(zhí)行道具和狀態(tài)的淺表比較(通過使用Object.is)。PureComponent
。
shouldComponentUpdate() {
// a shallow comparison of all the props and state
}
render() {{this.props.name};
}
}class Driver extends React.PureComponent { render() {{this.props.name}; } }
功能部件
React.memo
React.memo
這樣做!React.memo
是針對函數(shù)組件的。React.memo
將重用上次渲染的結(jié)果,而不是計算新結(jié)果。
const Driver = function(props) {
return{props.name};
};
// exporting the memoized function component
export default React.memo(Driver);{ name: "Charles Leclerc" }
{ name: "Daniel Ricciardo" }
React.memo
看到道具沒有更改。React.memo
與React.PureComponent
相當(dāng),因為它對所有道具進行了淺層比較(使用對象.is如果您想獲得更多的控制權(quán)并負責(zé)比較,React.memo
接受第二個參數(shù),即比較函數(shù)。這使得它在基于類的組件中與shouldComponentUpdate
相當(dāng)。false
時,函數(shù)組件將像平常一樣執(zhí)行。true
時,函數(shù)組件將不執(zhí)行,并且將使用前面的結(jié)果。shouldComponentUpdate
相反!
const Driver = function(props) {
return{props.name};
};
// the custom comparison function
const comparisonFn = function(prevProps, nextProps) {
return prevProps.name === nextProps.name;
};
// exporting the memoized function component
export default React.memo(Driver, comparisonFn);count
和一個是unusedCount
。顧名思義,它仍將被閑置。count
和unusedCount。
count
以及該子組件渲染的次數(shù)。count
時,具有上述優(yōu)化之一的組件才會渲染。當(dāng)更新unusedCount
時,其他的也會渲染。React.memo
與React.useMemo
React.memo
是一個高階組件,因為它接受一個組件并返回新的/記憶的組件。React.useMemo
是一個hook(它是一個函數(shù))。它接受一個函數(shù)并返回所傳遞函數(shù)的記憶返回值。React.useMemo
React.useMemo
接受函數(shù)作為第一個參數(shù)。此函數(shù)返回的值是React.useMemo
將返回的值。只有在必要時才會重新計算。React.useMemo
將返回已記憶/已記憶的值(如果沒有)。React.useMemo
是否應(yīng)該通過第二個參數(shù)(數(shù)組)重新計算結(jié)果。傳遞的函數(shù)返回的值只有在依賴項數(shù)組中的某些內(nèi)容發(fā)生更改時才會再次計算。不傳遞任何內(nèi)容將導(dǎo)致每次呈現(xiàn)組件時都計算該值(并導(dǎo)致函數(shù)運行)。eslint-plugin-react-hooks
,用于在違反hook規(guī)則時發(fā)出警告。正在完成的依賴關(guān)系數(shù)組由該包中名為exhaustive-deps
的規(guī)則檢查。
function calculatePodiums(name) {
// very expensive calculation
return numResult;
}
const Driver = function(props) {
const numOfPodiums = React.useMemo(() => calculatePodiums(props.name), [
props.name
]);
return (My name is: {props.name}I drive for: {props.team}I have been on the podium {numOfPodiums} times);
};{ name: "Kimi R?ikk?nen", team: "Ferrari" }
numOfPodiums
并使用該計算的結(jié)果進行呈現(xiàn)。{ name: "Kimi R?ikk?nen", team: "Alfa Romeo Racing" }
numOfPodiums
的memo/membered值。{ name: "Antonio Giovinazzi", team: "Alfa Romeo Racing" }
React.useCallback
React.useMemo
用法的快捷方式。React.useMemo
返回已記憶的值.React.useCallback
返回已記憶的函數(shù).
return function doTheThing(a, b) {
// do the thing
}
}
}, [a, b])doTheThing。
// do the thing
}
}, [a, b])doTheThing
的函數(shù)。React.useMemo
一樣,第二個參數(shù)是一個依賴項數(shù)組。React.useCallback
僅當(dāng)該數(shù)組中的某些內(nèi)容發(fā)生更改時才會返回更改。