大家好,我卡頌。
雖然React
官網用大量篇幅介紹最佳實踐,但因JSX
語法的靈活性,所以總是會出現奇奇怪怪的React
寫法。
本文介紹2種奇怪(但在某些場景下有意義)的React
寫法。也歡迎大家在評論區討論你遇到過的奇怪寫法。
歡迎加入人類高質量前端交流群,帶飛
ref的奇怪用法
這是一段初看讓人很困惑的程式碼:
function App() {
const [dom, setDOM] = useState(null);
return <div ref={setDOM}></div>;
}
讓我們來分析下它的作用。
首先,ref
有兩種形式(曾經有3種):
- 形如
{current: T}
的資料結構 - 回撥函式形式,會在
ref
更新、銷燬時觸發
例子中的setDOM
是useState
的dispatch
方法,也有兩種呼叫形式:
- 直接傳遞更新後的值,比如
setDOM(xxx)
- 傳遞更新狀態的方法,比如
setDOM(oldDOM => return /* 一些處理邏輯 */)
在例子中,雖然反常,但ref
的第二種形式和dispatch
的第二種形式確實是契合的。
也就是說,在例子中傳遞給ref
的setDOM
方法,會在div對應DOM更新、銷燬時執行,那麼dom
狀態中儲存的就是div對應DOM的最新值。
這麼做一定程度上實現了感知DOM的實時變化,這是單純使用ref
無法具有的能力。
useMemo的奇怪用法
通常我們認為useMemo
用來快取變數props
,useCallback
用來快取函式props
。
但在實際專案中,如果想透過快取props的方式達到子元件效能最佳化的目的,需要同時保證:
- 所有傳給子元件的
props
的引用都不變(比如透過useMemo
) - 子元件使用
React.memo
類似這樣:
function App({todos, tab}) {
const visibleTodos = useMemo(
() => filterTodos(todos, tab),
[todos, tab]);
return <Todo data={visibleTodos}/>;
}
// 為了達到Todo效能最佳化的目的
const Todo = React.memo(({data}) => {
// ...省略邏輯
})
既然useMemo
可以快取變數,為什麼不直接快取元件的返回值呢?類似這樣:
function App({todos, tab}) {
const visibleTodos = useMemo(
() => filterTodos(todos, tab),
[todos, tab]);
return useMemo(() => <Todo data={visibleTodos}/>, [visibleTodos])
}
function Todo({data}) {
return <p>{data}</p>;
}
如此,需要效能最佳化的子元件不再需要手動包裹React.memo
,只有當useMemo
依賴變化後子元件才會重新render
。
總結
除了這兩種奇怪的寫法外,你還遇到哪些奇怪的React
寫法呢?