React 最新特性Concurrent(并發(fā))模式 理解(一)

最近,React官方放出了最新特性Concurrent模式(實(shí)驗(yàn)階段)的文檔。又是一個(gè)非常實(shí)用的特性。

什么是并發(fā)?官方解釋是:并發(fā)模式是一些可以幫助React保持響應(yīng)地和友好地去適應(yīng)用戶設(shè)備性能和網(wǎng)速。
也就是React可以根據(jù)用戶設(shè)備的性能和網(wǎng)速做出一些調(diào)整,以保證頁(yè)面能夠更流暢的渲染。

React給出了兩種并發(fā)的應(yīng)用:數(shù)據(jù)獲取和UI渲染

傳統(tǒng)的UI渲染是阻塞式的,在當(dāng)前任務(wù)沒(méi)有執(zhí)行完畢時(shí)不會(huì)去進(jìn)行下一步的操作,即使有更加緊急的任務(wù)也必須等到前面的任務(wù)執(zhí)行完畢。React對(duì)此做出了優(yōu)化,使得UI渲染是可以打斷的,在執(zhí)行Ui渲染時(shí),如果有更加緊急的任務(wù),將會(huì)先去執(zhí)行該任務(wù),等待該任務(wù)執(zhí)行完畢后再去繼續(xù)執(zhí)行前面的任務(wù)。React官方給出了一個(gè)例子:過(guò)濾列表的例子。我們?cè)谳斎肟蜉斎雰?nèi)容時(shí),列表就會(huì)立刻進(jìn)行渲染,但渲染是阻塞的,渲染時(shí)將不能進(jìn)行輸入,頁(yè)面會(huì)出現(xiàn)卡頓,傳統(tǒng)情況下,為了減少渲染次數(shù),我們會(huì)用節(jié)流和防抖方式進(jìn)行優(yōu)化,但是這樣還是有些不友好的體驗(yàn)。React引入并發(fā)模式后,所有的操作都是可以打斷的,我們繼續(xù)輸入的時(shí)候,渲染就會(huì)被打斷,在你輸入的空隙就會(huì)繼續(xù)渲染,這樣就使得頁(yè)面的渲染更加流暢。當(dāng)然這只是非常基本的一種情況,實(shí)際上,React還可以做的更多。

React官方把并發(fā)模式比作了git的分支操作,React會(huì)在主分支上進(jìn)行操作時(shí),其他的操作可以在其他分支上(后臺(tái))完成,等主分支上的任務(wù)執(zhí)行完畢后,就會(huì)拿到其它分支上的執(zhí)行結(jié)果進(jìn)行處理。

在React16.6引入了Suspense,可以優(yōu)雅的進(jìn)行異步組件的加載處理。但是現(xiàn)在,Suspense可做的更多。
例如數(shù)據(jù)的獲取:

const resource = fetchProfileData();

function ProfilePage() {
  return (
    <Suspense fallback={<h1>Loading profile...</h1>}>
      <ProfileDetails />
      <Suspense fallback={<h1>Loading posts...</h1>}>
        <ProfileTimeline />
      </Suspense>
    </Suspense>
  );
}

function ProfileDetails() {
  // 嘗試去讀取用戶信息,即使數(shù)據(jù)還沒(méi)有獲取到
  const user = resource.user.read();
  return <h1>{user.name}</h1>;
}

function ProfileTimeline() {
  // 嘗試去帖子列表,即使數(shù)據(jù)還沒(méi)有獲取到
  const posts = resource.posts.read();
  return (
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.text}</li>
      ))}
    </ul>
  );
}

這也就是并發(fā)模式的數(shù)據(jù)加載方式;在數(shù)據(jù)還沒(méi)有加載到的時(shí)候,會(huì)通過(guò)Susepnse顯示一個(gè)降級(jí)的渲染。注意:這里的加載方式必須使用被封裝好的并發(fā)式的請(qǐng)求工具函數(shù)。React官方給我們介紹了兩種:Rely、和一個(gè)簡(jiǎn)單的fake api,具體使用可以去React官網(wǎng)查找。通過(guò)這種方式就可以在數(shù)據(jù)加載的時(shí)候優(yōu)雅地提供一個(gè)過(guò)渡狀態(tài)。

另一個(gè)是UI渲染的并發(fā)模式,我們可以在例如按鈕點(diǎn)擊時(shí)不去立刻進(jìn)行操作(比如進(jìn)入一個(gè)空白頁(yè)面),而是給他一個(gè)延時(shí),在延時(shí)結(jié)束有才會(huì)進(jìn)行操作(比如頁(yè)面的跳轉(zhuǎn)),在此期間,我們可以去加載數(shù)據(jù),之后的跳轉(zhuǎn)會(huì)是一個(gè)平滑的過(guò)渡,以此可以提升用戶體驗(yàn)。

關(guān)鍵API:useTransition,他會(huì)返回一個(gè)startTransition函數(shù)和isPending狀態(tài)。舉個(gè)栗子:

function App() {
// 獲取數(shù)據(jù)
  const [resource, setResource] = useState(initialResource);
 // 使用一個(gè)Transition,延時(shí)三秒
  const [startTransition, isPending] = useTransition({
    timeoutMs: 3000
  });
  return (
    <>
      <button
        disabled={isPending}
        onClick={() => {
          // 點(diǎn)擊之后會(huì)在三秒后才進(jìn)行startTransition里的操作
          startTransition(() => {
            const nextUserId = getNextId(resource.userId);
            setResource(fetchProfileData(nextUserId));
          });
        }}
      >
        Next
      </button>
      {isPending ? " Loading..." : null}
      <ProfilePage resource={resource} />
    </>
  );
}

具體參考:React官方文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。