大家好,我是若川。持續組織了6個月源碼共讀活動,感興趣的可以點此加我微信 ruochuan12?參與,每周大家一起學習200行左右的源碼,共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》?包含20余篇源碼文章。歷史面試系列
今天給大家帶來一個令人興奮的消息:React 18 RC
版本發布啦!
去年6月份 React 18
發布 alpha
版本的時候,我已經第一時間試用,并且給大家分享了一波:【第一批吃螃蟹】試用 React 18 !
不過 alpha
畢竟還是屬于內部測試版本,可能還包括一些 bug
,功能也有很多沒放出來,大家不能在生產里去用。
這次發布的是 RC
版本(Release Candidate候選版本
):基本和最終發布的 stable
版本一樣,功能上不會再有太大變化,也更加穩定,大家可以嘗試在生產環境里用起來了 ~
安裝
安裝最新的 React 18 RC
版本:
npm?install?react@rc?react-dom@rc
客戶端渲染 API 的更新
如果你是第一次安裝 React 18
,可能會在控制臺看到一個警告:
Use createRoot instead. Until you switch to the new API, your app will behave as if it’s running React 17. Learn more: https://reactjs.org/link/switch-to-createroot
這是因為 React 18
中引入了一個新的 Root API
,它支持了最新的 concurrent renderer
,讓你可以自己決定是否啟用并發渲染的能力。
//?以前
import?{?render?}?from?'react-dom';
const?container?=?document.getElementById('app');
render(<App?tab="home"?/>,?container);//?現在
import?{?createRoot?}?from?'react-dom/client';
const?container?=?document.getElementById('app');
const?root?=?createRoot(container);
root.render(<App?tab="home"?/>);
同時,unmountComponentAtNode
也改為了 root.unmount
:
//?以前
unmountComponentAtNode(container);//?現在
root.unmount();
另外,React
還將之前 render
函數的回調函數干掉了,因為通常它在配合 Suspense
一起使用的時候得不到預期的效果:
//?以前
const?container?=?document.getElementById('app');
ReactDOM.render(<App?tab="ConardLiHome"?/>,?container,?()?=>?{console.log('rendered');
});//?現在
function?AppWithCallbackAfterRender()?{useEffect(()?=>?{console.log('rendered');});return?<App?tab="ConardLiHome"?/>
}const?container?=?document.getElementById('app');
const?root?=?ReactDOM.createRoot(container);
root.render(<AppWithCallbackAfterRender?/>);
還有一點, 如果你之前用了帶 hydrate
的服務端渲染,需要升級到:hydrateRoot
:
//?以前
import?{?hydrate?}?from?'react-dom';
const?container?=?document.getElementById('app');
hydrate(<App?tab="home"?/>,?container);//?現在
import?{?hydrateRoot?}?from?'react-dom/client';
const?container?=?document.getElementById('app');
const?root?=?hydrateRoot(container,?<App?tab="home"?/>);
服務端渲染 API 的更新
在這個版本中,React
為了完全支持服務端的 Suspense
和流式SSR,改進了 react-dom/server
的 API
,舊的 Node.js
流式 API
將會被完全棄用:
renderToNodeStream
棄用???,使用時將發出警告。對應新版
Node
環境的流式傳輸 API 為:renderToPipeableStream
。
另外,React 在這個版本還引入了新的 renderToReadableStream
來支持 Deno、Cloudflare worker
等其他環境的流式 SSR
和 Suspense
。
renderToString、renderToStaticMarkup
這兩個 API 還可以繼續用,但是對 Suspense
支持就不那么友好了。
想了解更多,可以看
React 18
官方工作組的博客:https://github.com/reactwg/react-18/discussions/22
批處理
React
中的批處理簡單來說就是將多個狀態更新合并為一次重新渲染,由于設計問題,在 React 18
之前,React
只能在組件的生命周期函數或者合成事件函數中進行批處理。默認情況下,Promise、setTimeout
以及其他異步回調是無法享受批處理的優化的。
//?React?18?之前function?handleClick()?{setCount(c?=>?c?+?1);setName('ConardLi');//?在合成事件中,享受批處理優化,只會重新渲染一次
}setTimeout(()?=>?{setCount(c?=>?c?+?1);setName('ConardLi');//?不會進行批處理,會觸發兩次重新渲染
},?1000);
從 React 18
開始,如果你使用了 createRoot
,所有的更新都會享受批處理的優化,包括Promise、setTimeout
以及其他異步回調函數中。
//?React?18?function?handleClick()?{setCount(c?=>?c?+?1);setName('ConardLi');//?只會重新渲染一次
}setTimeout(()?=>?{setCount(c?=>?c?+?1);setName('ConardLi');//?只會重新渲染一次
},?1000);
如果你有特殊的渲染需求,不想進行批處理,也可以使用 flushSync
手動退出:
import?{?flushSync?}?from?'react-dom';function?handleClick()?{flushSync(()?=>?{setCounter(c?=>?c?+?1);});//?更新?DOMflushSync(()?=>?{setFlag(f?=>?!f);});//?更新?DOM
}
想了解更多可以看
React 18
官方工作組的博客:https://github.com/reactwg/react-18/discussions/21
用于第三方庫的 API
React 18
的更新機制對于很多第三方 React
庫都是阻斷性的,如果想要適配 React 18
,這些庫可能要通過下面這些 API
做一些改造:
useId
是一個新的Hook
,用于在客戶端和服務端生成唯一id,同時避免hydration
的不兼容,這可以解決React 17
以及更低版本的問題。useSyncExternalStore
是一個新的Hook
,它允許外部存儲通過強制同步更新來支持并發讀取。推薦把這個新的API
推薦應用到任何與React
外部狀態集成的庫。useInsertionEffect
是一個新的Hook
,它可以解決CSS-in-JS
庫在渲染中動態注入樣式的性能問題。
放棄對 IE 的支持

在這個版本中,React 正式放棄了對 Internet Explorer
的支持。如果你的業務在 IE 還有用戶,只能繼續使用 React 17
及以下的版本了~。
如果大家想了解更多內容,歡迎查看 React
官方博客:https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助3000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。
識別上方二維碼加我微信、拉你進源碼共讀群
今日話題
略。分享、收藏、點贊、在看我的文章就是對我最大的支持~