偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

第一個(gè)可以在條件語(yǔ)句中使用的原生Hook誕生了

開發(fā) 前端
Use作為「讀取異步數(shù)據(jù)的原語(yǔ)」,可以配合Suspense實(shí)現(xiàn)「數(shù)據(jù)請(qǐng)求、加載、返回」的邏輯。

大家好,我卡頌。

在10月13日的first-class-support-for-promises RFC[1]中,介紹了一種新的hook? —— use。

use?什么?就是use?,這個(gè)hook?就叫use。這也是第一個(gè):

  • 可以在條件語(yǔ)句中書寫的hook
  • 可以在其他hook回調(diào)中書寫的hook

本文來(lái)聊聊這個(gè)特殊的hook。

use是什么

我們知道,async函數(shù)會(huì)配合await關(guān)鍵詞使用,比如:

async function load() {
const {name} = await fetchName();
return name;
}

類似的,在React組件中,可以配合use起到類似的效果,比如:

function Cpn() {
const {name} = use(fetchName());
return <p>{name}</p>;
}

可以認(rèn)為,use的作用類似于:

  • async await?中的await。
  • generator?中的yield。

use?作為「讀取異步數(shù)據(jù)的原語(yǔ)」,可以配合Suspense實(shí)現(xiàn)「數(shù)據(jù)請(qǐng)求、加載、返回」的邏輯。

舉個(gè)例子,下述例子中,當(dāng)fetchNote?執(zhí)行異步請(qǐng)求時(shí),會(huì)由包裹Note?的Suspense組件渲染「加載中狀態(tài)」。

當(dāng)請(qǐng)求成功時(shí),會(huì)重新渲染,此時(shí)note數(shù)據(jù)會(huì)正常返回。

當(dāng)請(qǐng)求失敗時(shí),會(huì)由包裹Note的ErrorBoundary組件處理失敗邏輯。

function Note({id}) {
const note = use(fetchNote(id));
return (
<div>
<h1>{note.title}</h1>
<section>{note.body}</section>
</div>
);
}

其背后的實(shí)現(xiàn)原理并不復(fù)雜:

  1. 當(dāng)Note組件首次render,fetchNote發(fā)起請(qǐng)求,會(huì)throw promise,打斷render流程。
  2. 以Suspense fallback作為渲染結(jié)果。
  3. 當(dāng)promise狀態(tài)變化后重新觸發(fā)渲染。
  4. 根據(jù)note的返回值渲染。

實(shí)際上這套「基于promise的打斷、重新渲染流程」當(dāng)前已經(jīng)存在了。use的存在就是為了替換上述流程。

與當(dāng)前React?中已經(jīng)存在的上述「promise流程」不同,use?僅僅是個(gè)「原語(yǔ)」(primitives),并不是完整的處理流程。

比如,use并沒有「緩存promise」的能力。

舉個(gè)例子,在下面代碼中fetchTodo?執(zhí)行后會(huì)返回一個(gè)promise,use?會(huì)消費(fèi)這個(gè)promise。

async function fetchTodo(id) {
const data = await fetchDataFromCache(`/api/todos/${id}`);
return {contents: data.contents};
}
function Todo({id, isSelected}) {
const todo = use(fetchTodo(id));
return (
<div className={isSelected ? 'selected-todo' : 'normal-todo'}>
{todo.contents}
</div>
);
}

當(dāng)Todo組件的id prop變化后,觸發(fā)fetchTodo重新請(qǐng)求是符合邏輯的。

但是當(dāng)isSelected prop變化后,Todo組件也會(huì)重新render,fetchTodo執(zhí)行后會(huì)返回一個(gè)新的promise。

返回新的promise不一定產(chǎn)生新的請(qǐng)求(取決于fetchTodo的實(shí)現(xiàn)),但一定會(huì)影響React接下來(lái)的運(yùn)行流程(比如不能命中性能優(yōu)化)。

這時(shí)候,需要配合React提供的cache API(同樣處于RFC)。

下述代碼中,如果id prop不變,fetchTodo始終返回同一個(gè)promise:

const fetchTodo = cache(async (id) => {
const data = await fetchDataFromCache(`/api/todos/${id}`);
return {contents: data.contents};
});

use的潛在作用

當(dāng)前,use的應(yīng)用場(chǎng)景局限在「包裹promise」。

但是未來(lái),use會(huì)作為客戶端中處理異步數(shù)據(jù)的主要手段,比如:

  • 處理context

use(Context)?能達(dá)到與useContext(Context)?一樣的效果,區(qū)別在于前者可以在條件語(yǔ)句,以及其他hook回調(diào)內(nèi)執(zhí)行。

  • 處理state

可以利用use實(shí)現(xiàn)新的原生狀態(tài)管理方案:

const currentState = use(store);
const latestValue = use(observable);

為什么不使用async await

本文開篇提到,use原語(yǔ)類似async await中的await,那為什么不直接使用async await呢?類似下面這樣:

// Note 是 React 組件
async function Note({id, isEditing}) {
const note = await db.posts.get(id);
return (
<div>
<h1>{note.title}</h1>
<section>{note.body}</section>
{isEditing ? <NoteEditor note={note} /> : null}
</div>
);
}

有兩方面原因。

一方面,async await的工作方式與React客戶端處理異步時(shí)的邏輯不太一樣。

當(dāng)await的請(qǐng)求resolve后,調(diào)用棧是從await語(yǔ)句繼續(xù)執(zhí)行的(generator中yield也是這樣)。

而在React中,更新流程是從根組件開始的,所以當(dāng)數(shù)據(jù)返回后,更新流程是從根組件從頭開始的。

改用async await的方式勢(shì)必對(duì)當(dāng)前React底層架構(gòu)帶來(lái)挑戰(zhàn)。最起碼,會(huì)對(duì)性能優(yōu)化產(chǎn)生不小的影響。

另一方面,async await這種方式接下來(lái)會(huì)在Server Component中實(shí)現(xiàn),也就是異步的服務(wù)端組件。

服務(wù)端組件與客戶端組件都是React組件,但前者在服務(wù)端渲染(SSR),后者在客戶端渲染(CSR),如果都用async await,不太容易從代碼層面區(qū)分兩者。

總結(jié)

use?是一個(gè)「讀取異步數(shù)據(jù)的原語(yǔ)」,他的出現(xiàn)是為了規(guī)范React在客戶端處理異步數(shù)據(jù)的方式。

既然是原語(yǔ),那么他的功能就很底層,比如不包括請(qǐng)求的緩存功能(由cache處理)。

之所以這么設(shè)計(jì),是因?yàn)镽eact?團(tuán)隊(duì)并不希望開發(fā)者直接使用他們。這些原語(yǔ)的受眾是React生態(tài)中的其他庫(kù)。

比如,類似SWR?、React-Query?這樣的請(qǐng)求庫(kù),就可以結(jié)合use?,再結(jié)合自己實(shí)現(xiàn)的請(qǐng)求緩存策略(而不是使用React?提供的cache方法)

各種狀態(tài)管理庫(kù),也可以將use作為其底層狀態(tài)單元的容器。

值得吐槽的是,Hooks?文檔中hook的限制那一節(jié)恐怕得重寫了。

參考資料

[1]first-class-support-for-promises RFC:https://github.com/acdlite/rfcs/blob/first-class-promises/text/0000-first-class-support-for-promises.md。

責(zé)任編輯:姜華 來(lái)源: 魔術(shù)師卡頌
相關(guān)推薦

2015-04-15 11:28:04

Apple Watch殺手應(yīng)用

2009-06-26 16:07:43

MyEclipse開發(fā)Hibernate程序

2014-05-26 15:25:43

網(wǎng)絡(luò)維護(hù)華為

2024-07-03 08:24:58

2013-10-30 22:10:28

Clouda程序

2022-10-17 10:28:05

Web 組件代碼

2023-06-01 08:24:08

OpenAIChatGPTPython

2022-11-01 07:23:55

Dockernetcore程序

2020-11-13 07:08:51

Spring Boot應(yīng)用Spring

2010-07-30 14:58:06

Flex應(yīng)用

2011-03-21 14:24:13

Debian 6

2012-02-08 11:15:38

HibernateJava

2013-01-14 09:44:58

JavaScriptJSJS框架

2011-03-03 21:04:08

bug程序員

2023-09-21 22:43:17

Django框架

2021-04-07 13:38:27

Django項(xiàng)目視圖

2011-08-29 15:12:24

UbuntuLinux模塊

2020-02-05 15:23:00

語(yǔ)言編程文言文

2021-12-13 11:31:36

排序數(shù)組數(shù)據(jù)結(jié)構(gòu)算法

2021-11-02 14:54:41

排序數(shù)組元素
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)