減少組件的渲染次數(shù),能提升 React App 的運(yùn)行時性能。通過寫法的優(yōu)化,可以減少不必要的組件渲染次數(shù)。
優(yōu)化寫法
1. 組件 Render 時,避免 state, props 沒變的子組件 Render
組件 Render 會導(dǎo)致的其子組件 Render,即使子組件的 state, props 沒變。
子組件用 PureComponent 和 React.memo 可以避免這種情況下的 Render。類組件用 PureComponent,函數(shù)組件用React.memo。示例:
// 類組件
class class ClassComp extends React.PureComponent{}
// 函數(shù)組件
function FnComp () {}
React.memo(FnComp)
2. 函數(shù)組件 Render 時,避免變化的函數(shù)屬性值,導(dǎo)致子組件 Render
函數(shù)組件中的函數(shù),每運(yùn)行一次,都會生成一個新的函數(shù)。如果這個函數(shù)是某個子組件的屬性,函數(shù) Render 一次,都會導(dǎo)致子組件的 Render。
用 useCallback 包裹函數(shù),可以避免這種情況下不必要的 Render。
const handleClick = useCallback(() => ..., [])
return (
<ChildComp onClick={handleClick}>
)
3. 組件 Render 時,屬性值避免用箭頭函數(shù)值,導(dǎo)致子組件 Render
如果子組件的屬性值是個箭頭函數(shù),父組件每次 Render,箭頭函數(shù)都是新的,會導(dǎo)致子組件的 Render。
屬性值用實(shí)例方法,就能避免這種情況。例如:
handleClick = () => {...},
render() {
return (
<ChildComp onClick={handleClick}>
)
}
Render Props 也出現(xiàn)這樣的問題。如:
<Mouse>
{mouse => (
<ChildComp pos={mouse}>
)}
</Mouse>
解決方案也是將其改成實(shí)例方法:
<Mouse>
{this.renderChild}
</Mouse>
4. 避免 Prop Drilling 導(dǎo)致的中間組件的 Render
Prop drilling 指將外層組件的 state 通過 props 一層層傳下去,傳遞到層級很深的子組件的過程。外層組件的 state 發(fā)生變化,中間組件都會 Render。
層級很深的子組件可以直接取到值,不需要中間屬性的傳遞,就能避免中間屬性的 Render。用 Context API 或 Redux,MobX 等狀態(tài)管理工具可以讓子組件直接取到值。用 Context API 的示例:
// 父組件提供數(shù)據(jù)
<ThemeContext.Provider value={{ theme: this.state.theme }}>
<Comp1>
<Comp2>
<Comp3>
<ThemeContext.Consumer>
{({theme}) => {
// 子組件拿值
}}
</ThemeContext.Consumer>
</Comp3>
</Comp2>
</Comp1>
</ThemeContext.Provider>