你們好,我是卡頌。html
今天和同事聊天,我說他是個鐵憨憨,不會和女生聊天。react
他啪的一下跳起來,「我可懂情調了」數組
「哦?那你來句土味情話。」markdown
他清清嗓子,壓低了腔調,望向遠方,緩緩道:ide
若是我是
component
,我對你的情愫在didMount
時燃起,直到我生命unmount
時熄滅函數
正當他沉浸在YY的世界沒法自拔時,我說:oop
你知道在
React18
,componentDidMount
和componentWillUnmount
可能調用屢次麼?學習
呵,渣男!ui
React
有個特性 —— Strict Mode
,被StrictMode
包裹的組件在DEV
環境會對不推薦寫法有更嚴格的提示與輔助檢測行爲。spa
<StrictMode>
<div> <ComponentOne /> <ComponentTwo /> </div>
</StrictMode>
複製代碼
輔助檢測行爲是指部分方法會被React
重複調用,幫助開發者更容易發現不規範使用這些方法時的潛在bug
。
全部會被重複調用的API見StrictMode文檔
舉個例子:
function App() {
const [num, update] = useState(0);
function onClick() {
update(num + 1);
}
console.log('render');
return (
<p onClick={onClick}>{num}</p>
);
}
複製代碼
當App
被StrictMode
包裹,點擊p
觸發更新後,App
組件會render
兩次。
在
v17
以前,例子中console.log
會執行兩次。但在v17
以後,React
覆寫了console
方法,因此console.log
只會執行一次,但組件實際會render
兩次
這麼作的目的是:做爲函數組件,App
的反作用應該在useEffect
回調中執行。
若是不規範書寫反作用(好比在組件函數體內寫反作用),那麼重複render
更容易暴露可能產生的bug
。
鋪墊完背景。接下來,讓咱們揭露React
善變的渣男行徑。
最近刷v18
討論組時忽然發現:StrictMode
中會增長一條Strict Effect
規則。
簡單的說,相似上文講到的部分API
在StrictMode
下會重複執行。
Strict Effect
規則會讓useEffect
、useLayoutEffect
在StrictMode
下也會重複執行。
好比:
function App() {
// 或useLayoutEffect
useEffect(() => {
// 邏輯1
return () => // 邏輯2;
}, [])
// ...
}
複製代碼
在當前React
中,組件mount
時,執行邏輯1。
而在Strict Effect
規則下,mount
時的邏輯以下:
組件mount
時,執行邏輯1
React
模擬組件unmount
,執行邏輯2
React
模擬組件mount
,執行邏輯1
注意,這裏useEffect
的依賴項是[]
,在以往的認知裏,依賴項爲空數組意味着該useEffect
邏輯只會在mount
時執行一次。
而在v18
的Strict Mode
,因爲包含了Strict Effect
規則,mount
時的useEffect
邏輯會被重複執行。
某種程度上講,這種打破開發者既有認知的Breaking Change
,比Concurrent Mode
更讓人難以接受。
那麼React
團隊爲何要設計這條規則呢?
Offscreen
是一個開發中的API
,預計會在某個v18
的小版本發佈。
他的功能相似Vue
中的keep-alive
,用來在組件失活時在後臺保存組件狀態。
舉個Tab
切換的例子,在Posts
和Archive
之間切換Tab
:
當切換到Posts
時,Archive
屬於失活狀態。
若是不須要保存狀態,則銷燬Archive
組件。當切換到Archive Tab
時,再從新mount Archive
。
當須要保存狀態時,只能將Posts
與Archive
的狀態保存在他們的父組件或狀態管理(好比Redux
)中。
而有了Offscreen API
,在Fiber
樹(能夠理解爲虛擬DOM
樹)層面,能夠保存失活的組件結構與狀態。
這個API
的應用場景主要包括:
切換路由時保存以前路由的狀態
預加載將要切換的路由
如今問題來了:當Offscreen
組件從失活變爲活動,會觸發什麼生命週期函數呢?
答案是:componentDidMount
以及:
useEffect(() => {
// 觸發這個邏輯...
}, [])
複製代碼
當Offscreen
組件從活動變爲失活時,會觸發componentWillUnmount
與:
useEffect(() => {
// ...
return () => {
// 觸發這個邏輯...
}
}, [])
複製代碼
因此,這些曾經被認爲在組件生命週期中只會觸發一次的方法,因爲Offscreen
,在將來可能會屢次觸發。
這也是React
提早在StrictMode
中加上Strict Effect
規則的緣由。
就像渣男變心前都會有些反常的舉動。
無論是Offscreen
仍是Concurrent Mode
,能夠預見隨着v18
的到來,React
會更強大,相應的學習曲線會更陡峭。
這既是機遇,也是挑戰。
千萬別等變化一股腦到眼前時再埋怨:
你個渣男,當初說好一心一意只會觸發一次,如今爲了妖豔新特性,背叛咱們的諾言。
到那時React
只會拍拍屁股轉身,留下不羈的背影: