react18他來了
react17都還沒捂熱油吭,react18突然就來了,沒有一點(diǎn)點(diǎn)防備,react官網(wǎng)已經(jīng)放出react18的介紹了官宣介紹。說了這么多,我們接下來看下官方多react18的介紹吧禀横。
新特新
1.Automatic batching
這個特性簡單來說,就是自動批量更新粥血,對于熟悉react的同學(xué)來說柏锄,對于下面這段代碼的渲染執(zhí)行一定不會陌生:
function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
function handleClick() {
setCount(c => c + 1); // Does not re-render yet
setFlag(f => !f); // Does not re-render yet
// React will only re-render once at the end (that's batching!)
}
return (
<div>
<button onClick={handleClick}>Next</button>
<h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
</div>
);
}
復(fù)制代碼
這段代碼我直接拷貝Dan Abramov對于Automatic batching特性說明的演示代碼(下面也是-_-),從注釋來看复亏,handleClick只會觸發(fā)一次渲染趾娃,為什么這么設(shè)計呢,用Dan的例子解釋:飯店的服務(wù)生不會你點(diǎn)了一個菜就會去通知廚房吧缔御,而是點(diǎn)完了之后再一次性告訴廚房抬闷,這么做的一個最大好處就是性能更好,接下來再看下一段代碼:
function App() {
const [count, setCount] = useState(0);
const [flag, setFlag] = useState(false);
function handleClick() {
fetchSomething().then(() => {
// React 17 and earlier does NOT batch these:
setCount(c => c + 1); // Causes a re-render
setFlag(f => !f); // Causes a re-render
});
}
return (
<div>
<button onClick={handleClick}>Next</button>
<h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1>
</div>
);
}
復(fù)制代碼
這一次會渲染兩次耕突,如果你深入react原理了解笤成,也不會很差異這種結(jié)果。簡單來說眷茁,異步任務(wù)執(zhí)行的時候其實(shí)已經(jīng)不在react的上下文環(huán)境了炕泳,react內(nèi)部是通過一個標(biāo)識來標(biāo)記是否需要批量更新的,render開始蔼卡,標(biāo)記為true喊崖,commit之后挣磨,標(biāo)記為false雇逞,異步任務(wù)再執(zhí)行,其實(shí)是在commit之后的茁裙,那么由于標(biāo)記為false塘砸,因此就不走批量了。大概就是這么個意思晤锥,有興趣的可以去深挖一下其中的實(shí)現(xiàn)細(xì)節(jié)掉蔬。不光是setTimeout,用dan的描述來說矾瘾,Updates inside of promises, setTimeout, native event handlers, or any other event were not batched in React by default
,因此promise/setTimeout/原生事件這些觸發(fā)的渲染都不會走批量女轿,當(dāng)然這些都是在18版本之前,18版本是怎樣的呢壕翩,還是上代碼吧:
setTimeout(() => {
setCount(c => c + 1);
setFlag(f => !f);
// React will only re-render once at the end (that's batching!)
}, 1000);
復(fù)制代碼
這里的異步任務(wù)就完成了自動的批量更新蛉迹,當(dāng)然在18版本要開啟這個功能的話,需要使用ReactDOM.createRoot去掛載我們的應(yīng)用放妈,如果我們還是使用ReactDOM.render的話北救,就不會啟用Automatic batching了荐操。 Automatic batching看起來很香,但是如果在一些場景我不想用呢珍策,官方也提供了解決辦法托启,請看例子:
import { flushSync } from 'react-dom'; // Note: react-dom, not react
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React has updated the DOM by now
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM by now
}
復(fù)制代碼
react work group還對Automatic batching做了很多的探討,包括對class/hooks的影響攘宙,有興趣的可以點(diǎn)擊這里查看屯耸。
看完對Automatic batching的說明后,還想補(bǔ)充一點(diǎn)蹭劈,react18版本前的blocking和concurrent模式其實(shí)已經(jīng)支持Automatic batching of multiple setStates
了肩民,大家可以去試試效果。最后再說一下unstable_batchedUpdates這個api链方,在18版本之前持痰,如果我們要手動批量,需要借助它去實(shí)現(xiàn)祟蚀,在18版本會依然支持工窍。
2.startTransition
這是一個嶄新的api,干什么的呢前酿,就是讓我們的應(yīng)用交互更加絲滑患雏,用來提升體驗(yàn)的,首先我們來了解一下它要解決一個什么樣的問題罢维。
官方工作小組里面的討論描述了一個場景淹仑,就是一個輸入框,接收用戶輸入肺孵,然后去篩選列表項匀借,場景很常見,但是會有一個性能隱患平窘,輸入這個操作可能會觸發(fā)大量的更新吓肋,導(dǎo)致頁面卡頓,給用戶直觀的感受就是輸入框有點(diǎn)卡瑰艘,不能實(shí)時顯示輸入的字符了是鬼,那么要怎么破呢,這讓我想到了react的并發(fā)渲染模式紫新,不就是要來解決這種優(yōu)先級的問題么均蜜,但是遺憾的是一直處于實(shí)驗(yàn)當(dāng)中,還不能安心用在工作中芒率,不扯遠(yuǎn)了囤耳,還是回到這個api上來,通過代碼我們對比一下:
// Urgent: Show what was typed
setInputValue(input);
// Not urgent: Show the results
setSearchQuery(input);
復(fù)制代碼
import { startTransition } from 'react';
// Urgent: Show what was typed
setInputValue(input);
// Mark any state updates inside as transitions
startTransition(() => {
// Transition: Show the results
setSearchQuery(input);
});
復(fù)制代碼
代碼片段1就是我們的常用寫法,用戶輸入就更新輸入框的狀態(tài)值進(jìn)行實(shí)時顯示輸入紫皇,然后去篩選列表慰安,setInputValue和setSearchQuery是同時執(zhí)行的;代碼片段2就使用了startTransition這個api聪铺,將setSearchQuery包裹其中化焕,實(shí)現(xiàn)手動的渲染任務(wù)優(yōu)先級排列,那么此時setInputValue的更新就高于setSearchQuery铃剔,因此用戶的輸入響應(yīng)就能得到保證撒桨,從而實(shí)現(xiàn)絲滑的體驗(yàn),官方還將其于setTimeout進(jìn)行了對比键兜,這里就不展開介紹了凤类,大家點(diǎn)擊這里查看。
3.New Suspense SSR Architecture
react18對SSR的性能進(jìn)行了新的改進(jìn)普气,引入了pipeToNodeWritable這個新的API谜疤,這個API可以替換renderToString,同時renderToNodeStream被標(biāo)記為Deprecated现诀,為什么會有這些改動呢夷磕,官方給出了解釋:
renderToString: Keeps working (with limited Suspense support).
renderToNodeStream: Deprecated (with full Suspense support, but without streaming).
pipeToNodeWritable: New and recommended (with full Suspense support and streaming)
復(fù)制代碼
出現(xiàn)了兩個需要注意的單詞:Suspense和streaming,Suspense這個組件在16.6.0被正式提出來仔沿,以前主要配合React.lazy用來異步加載組件的坐桩,而streaming就是指的React Server Components,現(xiàn)在react18對這兩者的支持就更加完善了封锉,因此react18的SSR將讓用戶更快的看見界面绵跷,更早的交互。 react18的SSR相比以前的SSR成福,有啥優(yōu)勢呢碾局,那我們先看下傳統(tǒng)的SSR流程吧:
On the server, fetch data for the entire app.
Then, on the server, render the entire app to HTML and send it in the response.
Then, on the client, load the JavaScript code for the entire app.
Then, on the client, connect the JavaScript logic to the server-generated HTML for the entire app (this is “hydration”).
復(fù)制代碼
以上四步必須嚴(yán)格按照流程一步步來,就像waterfall一樣闷叉,如果其中哪一步慢了擦俐,就會阻塞后面的流程,這樣用戶就需要忍受更長的白屏?xí)r間握侧,因此如果將上面四個步驟打散成一個個小的任務(wù)單元,那么先完成的任務(wù)就可以盡快呈現(xiàn)到用戶面前嘿期,這樣體驗(yàn)自然就更優(yōu)了品擎,這也是react18對Suspense和streaming改進(jìn)的動力所在,dan對這一部分有詳細(xì)的介紹备徐,點(diǎn)這里了解更多萄传。
漸進(jìn)式升級
每當(dāng)版本發(fā)生了重大更新,升級就是每個框架必須要考慮的一件事情,對于開發(fā)者來講秀菱,升級不能對我現(xiàn)有的項目造成影響吧振诬,放心,react考慮得比我們更多衍菱,其實(shí)vue也是一樣赶么,都提供了漸進(jìn)式平滑得升級策略。react官方說了脊串,放心升級吧辫呻,只需對應(yīng)用程序代碼進(jìn)行很少的更改或不做任何更改,其實(shí)不光是react18琼锋,react16到17放闺,對于升級其實(shí)都是成本很小的。
社區(qū)和react18工作小組
React 18 Working Group也是隨著react18版本的到來而成立的一個組織缕坎,工作職能跟w3c的working group類似怖侦,作為聯(lián)系社區(qū)與react18的橋梁,充分吸收來自各方的意見和討論谜叹,大家有興趣可以去了解一下础钠。
發(fā)布計劃
React 18 Library Alpha (Available now)
React 18 Public Beta (Months)
React 18 RC (Months)
React 18 (2-4 weeks after RC)
復(fù)制代碼
官方推出的發(fā)布計劃,大家拭目以待吧叉谜。
作者:putao
鏈接:https://juejin.cn/post/6971655993390317598
來源:稀土掘金
著作權(quán)歸作者所有旗吁。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處停局。