1. 前置說明
1.1 React的思維模式
view = fn(props, state, context)
- 只要參數(shù)發(fā)生改變,視圖一定發(fā)生
re-render
- 沒有被子組件使用的
props
會被丟棄趾访,比如傳遞了style
留储,但是子組件沒有操作style
屬性翼抠,或者沒有restProps
,則style
無效
1.2 React的變更
默認是指【指針的變更】获讳,不會監(jiān)聽對象的屬性變更
- 采用
Object.is(valA, valB)
進行比較 -
useState
產(chǎn)生的值阴颖,需要setState()
會觸發(fā)re-render
,和上一次一致時丐膝,不觸發(fā)re-render
- 可以采用
immutability-helper
對復雜對象進行處理
- 可以采用
useMemo
量愧,監(jiān)聽變量未改變,則產(chǎn)生的值也不會變
1.3 React父組件re-render的影響
若父組件發(fā)生了re-render
帅矗,則子組件也會re-render
- 使用JSX時偎肃,會轉(zhuǎn)成
React.createElement
-
React.memo
的使用 - 封裝
Provider
組件,子組件采用<Context.Provider value={{theme: this.state.theme, switchTheme: this.switchTheme}}> {this.props.children} </Context.Provider>
1.4 參考的輪子
2. 已知會導致re-render的可能性
- 組件
props
變更() - 組件監(jiān)聽的
dva
變更 - 組件監(jiān)聽的
context
變更 - 組件
eventBus
接受到消息 - 組件監(jiān)聽的
state
浑此,用戶會頻繁操作累颂,或一次操作,引發(fā)了多次setState凛俱,且不在一個effect中 - 父組件發(fā)生
re-render
- 父組件包含自更新組件紊馏,比如
key
會變化
3. 解決方案
3.1 props
的判定
React中將【屬性】【函數(shù)】【children】,統(tǒng)一傳遞給props
屬性(React.memo(組件名, (prev, next) => {})
)+ 回調(diào)函數(shù)(useCallback
蒲犬、useMemoziedFn
)
- 對于【基本數(shù)據(jù)類型】而言朱监,直接使用
React.memo
包裹即可 - 對于【復雜數(shù)據(jù)類型】而言,需要傳遞第二個參數(shù)進行判定暖哨,函數(shù)返回
false
會進行re-render
function areEqual(prevProps, nextProps) { /* 如果把 nextProps 傳入 render 方法的返回結(jié)果與 將 prevProps 傳入 render 方法的返回結(jié)果一致則返回 true赌朋, 否則返回 false */ } export default React.memo(MyComponent, areEqual);
- 深度比較
prev
和next
的值是否相等 -
lodash
的isEqual
或react-fast-compare
的isEqual
- 深度比較
- 對于【回調(diào)函數(shù)】而言凰狞,需要保證函數(shù)本身的指針不變(官方推薦采用
useCallback
)篇裁。但是若回調(diào)函數(shù)依賴外部變量沛慢,會使得指針發(fā)生改變,則失效达布;若不監(jiān)聽變量团甲,則會產(chǎn)生問題,也失效黍聂。這時useMemoizedFn
就有作用了
3.2 useSelector
的使用
-
不要返回大對象
反例:const app = useSelector((state: { app: any }) => state.app) || {};
- 利用第二個參數(shù)進行深度比較躺苦,來減少
re-render
3.3 useContext
的使用
- 存儲的屬性顆粒度要小,不要直接存儲大對象
- 封裝Provider
3.4 eventBus的使用
注銷時产还,off消費函數(shù)
useEffect(() => {
EventEmitter.on('refreshTagList', refreshCbk);
return () => {
EventEmitter.off('refreshTagList', refreshCbk);
};
}, []);
3.5 本組件優(yōu)化策略
-
usememo
(降低非必要渲染) -
useDebounceFn
(防抖) - 多個
setState
合并 -
useUpdateEffect
(減少初始化的不必要數(shù)據(jù)變更)
3.6 父組件re-render
同3.1策略
3.7 自更新組件
抽離出自更新組件到祖父級(最好存放在的組件中)