我們遇到了問題,非同步很難。
假設您有一個簡單的 GET API,一個接收 searchText 作為參數的搜尋。您使用您偏好的 http 請求工具來呼叫它並得到一個承諾,它解析為您正在搜尋的任何內容的清單。
如何在 React 元件中呼叫它?
首先,需要注意一件事,我所描述的可以建模為:
result = await searchAPI(searchText);
讓我們在這裡了解一下概念。 這是一個推導。對於每個版本的 searchText,您可以獲得不同的結果。但這裡有一些問題:
如何在 React 中稱為派生?
使用第三方函式庫,例如 TanStack Query 和 SWR 解決了我們的問題。它們為我們提供了可以在 React 元件中使用的鉤子,接收我們的狀態和屬性,並在 API 發生變化時重新計算(重新取得)。看這個例子:
const { data: searchResult, loading } = useQuery({queryKey: [search, searchText],queryFn: getSearch,});
好的,我們解決了非同步推導,對吧?
其實不是。
順便說一句,我總是建議只使用其中一個庫,它們很棒,並且可以在更複雜的情況下節省大量時間(例如重新獲取、重試、緩存控制等),但我們不能指望第三個- 解決React 概念問題的聚會。
再次回到反應性,我們需要有一種方法來處理派生模型中的非同步情況。 React 應該為我們提供一個針對這種情況的原語。嗯,直到版本 18 之前我們都沒有它,但在版本 19 中就不同了。
React 19 引進了一個名為 use 的新原語。是的,命名有點令人困惑,但它在 React 反應模型中的作用非常重要。有了它,我們可以在元件渲染期間解決承諾。 缺失的推導。
在此之前,在元件渲染期間呼叫 fetch 的唯一方法是使用 useEffect,呼叫 Promise 並在 then 子句中,使用回應中的值設定狀態。這在某種程度上是有效的,但我們在使用效果來實現這一點時遇到了所有問題。
use 原語允許我們在元件渲染期間解析 Promise,讓我們可以使用狀態和 props 來建立 Promise,然後解析這些 Promise 並將其用於我們的函數和 JSX。
const useCountTotal = (count: number) => { const countTotalPromise = useMemo(() => genericPromise(count), [count]); const result = use(countTotalPromise); return result; } function AsyncDerivation({count}: { count: number}) { const result = useCountTotal(count); return ( <div>Total count is: {result}</div> ) }
在我寫這篇文章的時候,我們還沒有 React 19 的最終版本。有一些警告,並且該原語可能會在未來發展以在更多地方工作。
原始使用的一個具體問題是它需要與 Suspense 一起使用,這是有充分理由的。
await 的概念很好,但是與 React 元件結合時有一個缺陷。您不能只在渲染期間使用await。 React 呼叫元件來取得 JSX 回應,並在流程中使用它來渲染 UI。
如果我們可以在等待中停止所有事情,React 就無法存取該元件的子元件並繼續其工作,直到樹的末端。我們會停止渲染流程並使 UI 不更新並凍結。
如何解決?
我們可以看一下我在本文中使用的兩個範例。第一個採用傳回標誌(例如載入)的方法,而不是阻塞渲染流。當承諾得到解決時,它會引發重新渲染,更新標誌,載入變為 false 並且資料接收回應資料。
使用方式不同。它的行為確實類似於await原語,因此元件渲染流在那裡停止,直到解析度。
等等,等等,你說這是一個問題,對吧?
拯救懸念來了。當您使用use 原語時,它將包裝在Suspense 元件中,渲染流將停止等待use 分辨率,並且用戶將獲得在UI 上渲染的後備(通常是加載旋轉器或骨架,表明我們正在那裡加載一些東西)。
當使用承諾解決後,我們將繼續渲染並相應地更新 UI。無需使用useEffect。
use 原語對於旨在使用 Suspense 並處理異步行為的庫作者來說非常有用。對於應用程式開發人員來說,它修復了基本反應性模型中的另一種情況,這非常適合簡單的用例。由於它封裝了 Promise,因此它不僅限於 http 請求,還適用於所有非同步情況和外部 API 使用,這可以為生態系統添加更多資源。
以上是React 中的非同步派生的詳細內容。更多資訊請關注PHP中文網其他相關文章!