欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

React團(tuán)隊測試并發(fā)特性詳解

 更新時間:2022年08月23日 14:55:50   作者:魔術(shù)師卡頌  
這篇文章主要為大家介紹了React團(tuán)隊測試并發(fā)特性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

React18進(jìn)入大家視野已經(jīng)有一段時間了,不知道各位有沒有嘗試并發(fā)特性呢?

當(dāng)啟用并發(fā)特性后,React會從同步更新變?yōu)楫惒?、帶?yōu)先級、可中斷的更新。

這也為編寫單元測試帶來了一些難度。

本文來聊聊React團(tuán)隊如何測試并發(fā)特性。

遇到的困境

主要有兩個問題需要面對。

1. 如何表達(dá)渲染結(jié)果?

React可以對接不同宿主環(huán)境的渲染器,大家最熟悉的渲染器想必是ReactDOM,用于對接瀏覽器與Node環(huán)境(SSR)。

對于一些場景,可以用ReactDOM的輸出結(jié)果做測試。

比如,下面是使用ReactDOM的輸出結(jié)果測試無狀態(tài)組件的渲染結(jié)果是否符合預(yù)期(測試框架是jest):

	it('should render stateless component', () => {
		const el = document.createElement('div');
		ReactDOM.render(<FunctionComponent name="A" />, el);
		expect(el.textContent).toBe('A');
	});

這里有個不方便的地方 —— 這個用例依賴瀏覽器環(huán)境與DOM API(比如用到document.createElement)。

對于測試React內(nèi)部運行機制這樣的場景,摻雜了宿主環(huán)境相關(guān)信息顯然會讓測試用例編寫起來更繁瑣。

2. 如何測試并發(fā)環(huán)境?

如果將上文的用例中ReactDOM.render改為ReactDOM.createRoot,那么用例就會失敗:

// 之前
ReactDOM.render(<FunctionComponent name="A" />, el);
expect(el.textContent).toBe('A');
// 之后
ReactDOM.createRoot(el).render(<FunctionComponent name="A" />);
expect(el.textContent).toBe('A');

這是因為在新的架構(gòu)下,很多同步更新變成了并發(fā)更新,當(dāng)render執(zhí)行后,頁面還沒完成渲染。

要讓上述用例成功,最簡單的修改方式是:

ReactDOM.createRoot(el).render(<FunctionComponent name="A" />);
setTimeout(() => {
  // 異步獲取結(jié)果
  expect(el.textContent).toBe('A');
})

如何優(yōu)雅的應(yīng)對這種變化?

React的應(yīng)對策略

接下來我們來看React團(tuán)隊的應(yīng)對方式。

首先來看第一個問題 —— 如何表達(dá)渲染結(jié)果?

既然ReactDOM渲染器對應(yīng)瀏覽器、Node環(huán)境,ReactNative渲染器對應(yīng)Native環(huán)境。

那能不能為測試內(nèi)部運行流程專門開發(fā)一個渲染器呢?

答案是肯定的。

這個渲染器叫React-Noop-Renderer。

簡單的說,這個渲染器會渲染出純JS對象。

實現(xiàn)一個渲染器

React內(nèi)部有個叫Reconciler的包,他會引用一些操作宿主環(huán)境的API。

比如如下方法用于向容器中插入節(jié)點:

function appendChildToContainer(child, container) {
	// 具體實現(xiàn)
}

對于瀏覽器環(huán)境(ReactDOM),使用appendChild方法實現(xiàn)即可:

function appendChildToContainer(child, container) {
	// 使用appendChild方法
  container.appendChild(child);
}

打包工具(rollup)將Reconciler包與上述這類針對瀏覽器環(huán)境的API打包起來,就是ReactDOM包。

React-Noop-Renderer中,與ReactDOM中的DOM節(jié)點對標(biāo)的是如下數(shù)據(jù)結(jié)構(gòu):

const instance = {
  id: instanceCounter++,
  type: type,
  children: [],
  parent: -1,
  props
};

注意其中的children字段,用于保存子節(jié)點。

所以appendChildToContainer方法在React-Noop-Renderer中可以實現(xiàn)的很簡單:

function appendChildToContainer(child, container) {
	const index = container.children.indexOf(child);
	if (index !== -1) {
		container.children.splice(index, 1);
	}
	container.children.push(child);
};

打包工具將Reconciler包與上述這類針對React-Noop的API打包起來,就是React-Noop-Renderer包。

基于React-Noop-Renderer,可以完全脫離正常的宿主環(huán)境,測試Reconciler內(nèi)部的邏輯。

接下來來看第二個問題。

如何測試并發(fā)環(huán)境?

并發(fā)特性再復(fù)雜,說到底也只是各種異步執(zhí)行代碼的策略,最終執(zhí)行策略的API不外乎setTimeoutsetInterval、Promise等。

jest中,可以模擬這些異步API,控制他們的執(zhí)行時機。

比如上面的異步代碼,在React中的測試用例會這么寫:

// 測試用例修改后:
await act(() => {
  ReactDOM.createRoot(el).render(<FunctionComponent name="A" />);
})
expect(el.textContent).toBe('A');

act方法來自jest-react包,他的內(nèi)部會執(zhí)行jest.runOnlyPendingTimers方法,讓所有等待中的計時器觸發(fā)回調(diào)。

比如如下代碼:

setTimeout(() => {
  console.log('執(zhí)行')
}, 9999999)

執(zhí)行jest.runOnlyPendingTimers后會立刻打印執(zhí)行。

通過這種方式,人為控制React并發(fā)更新的速度,同時對框架代碼0侵入。

除此之外,用于驅(qū)動并發(fā)更新的Scheduler(調(diào)度器)模塊,本身也有一個針對測試的版本。

在這個版本中,開發(fā)者可以手動控制Scheduler的輸入、輸出。

比如,我想測試組件卸載時useEffect回調(diào)的執(zhí)行順序。

如下面代碼所示,其中Parent為掛載的被測試組件:

function Parent() {
  useEffect(() => {
    return () => Scheduler.unstable_yieldValue('Unmount parent');
  });
  return <Child />;
}
function Child() {
  useEffect(() => {
    return () => Scheduler.unstable_yieldValue('Unmount child');
  });
  return 'Child';
}
await act(async () => {
  root.render(<Parent />);
});

根據(jù)yieldValue的插入順序是否符合預(yù)期,就能確定useEffect的邏輯是否符合預(yù)期:

expect(Scheduler).toHaveYielded(['Unmount parent', 'Unmount child']);

總結(jié)

React中測試用例的編寫策略為:

  • 可以用ReactDOM測的用例,一般結(jié)合ReactDOMReactTestUtils(瀏覽器環(huán)境的輔助方法)完成
  • 需要把控中間過程的用例,使用Scheduler的測試包,用Scheduler.unstable_yieldValue記錄過程信息
  • 脫離宿主環(huán)境,單獨測試React內(nèi)部運行流程的,使用React-Noop-Renderer
  • 測試并發(fā)下的場景,需要結(jié)合上述工具與jest-react一起使用

如果想深入學(xué)習(xí)下React中與測試相關(guān)的技巧,可以看下司徒正美老師的作品anu。

這是個類React框架,但能跑通800+的React用例。里面實現(xiàn)了ReactTestUtils、React-Noop-Renderer的簡化版。

以上就是React團(tuán)隊測試并發(fā)特性詳解的詳細(xì)內(nèi)容,更多關(guān)于React團(tuán)隊測試并發(fā)特性的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • React 自動聚焦字段使用詳解

    React 自動聚焦字段使用詳解

    這篇文章主要為大家介紹了React 自動聚焦字段使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 阿里低代碼框架lowcode-engine自定義設(shè)置器詳解

    阿里低代碼框架lowcode-engine自定義設(shè)置器詳解

    這篇文章主要為大家介紹了阿里低代碼框架lowcode-engine自定義設(shè)置器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Webpack 4.x搭建react開發(fā)環(huán)境的方法步驟

    Webpack 4.x搭建react開發(fā)環(huán)境的方法步驟

    這篇文章主要介紹了Webpack 4.x搭建react開發(fā)環(huán)境的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 淺談React Router關(guān)于history的那些事

    淺談React Router關(guān)于history的那些事

    這篇文章主要介紹了淺談React Router關(guān)于history的那些事,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • react 項目 中使用 Dllplugin 打包優(yōu)化技巧

    react 項目 中使用 Dllplugin 打包優(yōu)化技巧

    在用 Webpack 打包的時候,對于一些不經(jīng)常更新的第三方庫,比如 react,lodash,vue 我們希望能和自己的代碼分離開,這篇文章主要介紹了react 項目 中 使用 Dllplugin 打包優(yōu)化,需要的朋友可以參考下
    2023-01-01
  • React?保留和重置State

    React?保留和重置State

    這篇文章主要為大家介紹了React?保留和重置State實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • React18新增特性介紹

    React18新增特性介紹

    react歷次版本迭代主要想解決的是兩類導(dǎo)致網(wǎng)頁卡頓的問題,分別是cpu密集型任務(wù)和io密集型任務(wù)導(dǎo)致的卡頓問題,react18新增特性就是為了解決上述問題
    2022-09-09
  • 淺談React多個setState會調(diào)用幾次

    淺談React多個setState會調(diào)用幾次

    在React的生命周期鉤子和合成事件中,多次執(zhí)行setState,會被調(diào)用幾次,本文就詳細(xì)的介紹一下,感興趣的可以了解一下
    2021-11-11
  • Vite搭建React項目的方法步驟

    Vite搭建React項目的方法步驟

    這篇文章主要介紹了Vite搭建React項目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • React?Hook?Form?優(yōu)雅處理表單使用指南

    React?Hook?Form?優(yōu)雅處理表單使用指南

    這篇文章主要為大家介紹了React?Hook?Form?優(yōu)雅處理表單使用指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03

最新評論