使用 Suspense 的載入狀態
您可能已經注意到,我們提到使用 usePreloadedQuery
和 useLazyLoadQuery
會呈現從伺服器獲取查詢的資料,但我們沒有詳細說明在資料仍在獲取時如何呈現載入 UI(例如微光效果)。我們將在本節中介紹。
為了在獲取查詢時呈現載入狀態,我們依賴 React Suspense。Suspense 是 React 的一項新功能,允許元件中斷或「暫停」呈現,以便等待某些非同步資源(例如程式碼、圖像或資料)載入;當元件「暫停」時,它會向 React 表明該元件尚未「準備好」呈現,並且在它等待的非同步資源載入之前不會準備好。當資源最終載入時,React 將嘗試再次呈現該元件。
此功能對於元件表達它們為了呈現而需要的非同步依賴項(如資料、程式碼或圖像)非常有用,並且讓 React 協調在這些非同步資源可用時在元件樹中呈現載入狀態。更廣泛地說,使用 Suspense 可以讓我們更好地控制,以便在我們的應用程式首次載入或轉換為不同狀態時實作更精心設計的載入狀態,並有助於防止載入元素(如旋轉器)意外閃爍,這種情況在載入序列未明確設計和協調時經常發生。
請注意,這並不表示「用於資料獲取的 Suspense」已準備好進行一般實作和採用。用於資料獲取的 Suspense 的支援、一般指導和使用要求尚未準備好,React 團隊仍在為即將發布的 React 版本定義此指導將是什麼。
即使在 React 17 中使用 Suspense 時會有一些限制,Relay Hooks 是穩定的,並且正在支援即將發布的 React 版本。
如需更多資訊,請參閱我們的Suspense 相容性指南。
使用 Suspense 邊界的載入後備
當元件暫停時,我們需要呈現後備來代替元件,同時等待它變成「準備好」。為了這樣做,我們使用 React 提供的 Suspense
元件
const React = require('React');
const {Suspense} = require('React');
function App() {
return (
// Render a fallback using Suspense as a wrapper
<Suspense fallback={<LoadingGlimmer />}>
<CanSuspend />
</Suspense>
);
}
Suspense
元件可用於包裝任何元件;如果目標元件暫停,Suspense
將呈現提供的後備,直到其所有子系都變成「準備好」(即,直到子樹內所有暫停的元件都解析)。通常,後備用於呈現後備載入狀態,例如微光效果和佔位符。
通常,我們應用程式中的不同內容可能會暫停,因此我們可以顯示載入狀態,直到它們通過使用 Suspense
解析
/**
* App.react.js
*/
const React = require('React');
const {Suspense} = require('React');
function App() {
return (
// LoadingGlimmer is rendered via the Suspense fallback
<Suspense fallback={<LoadingGlimmer />}>
<MainContent /> {/* MainContent may suspend */}
</Suspense>
);
}
讓我們精煉一下這裡發生的事情
- 如果
MainContent
因為等待某些非同步資源(如資料)而暫停,則包裝MainContent
的Suspense
元件將檢測到它已暫停,並且將呈現fallback
元素(在本例中為LoadingGlimmer
),直到MainContent
準備好呈現。請注意,這也傳遞性地包括MainContent
的子系,這些子系也可能暫停。
Suspense 的優點在於您可以精細控制如何累積元件樹中不同部分的載入狀態
/**
* App.react.js
*/
const React = require('React');
const {Suspense} = require('React');
function App() {
return (
// A LoadingGlimmer for all content is rendered via the Suspense fallback
<Suspense fallback={<LoadingGlimmer />}>
<MainContent />
<SecondaryContent /> {/* SecondaryContent can also suspend */}
</Suspense>
);
}
- 在這種情況下,
MainContent
和SecondaryContent
都可能在載入其非同步資源時暫停;通過將兩者都包裝在Suspense
中,我們可以顯示單一載入狀態,直到它們全部都準備好,然後在一切都成功載入後,在單一繪製中呈現整個內容。 - 事實上,
MainContent
和SecondaryContent
可能會因為獲取資料以外的不同原因而暫停,但相同的Suspense
元件可用於呈現後備,直到子樹中的所有元件都準備好呈現。請注意,這也傳遞性地包括MainContent
或SecondaryContent
的子系,這些子系也可能暫停。
相反地,您也可以決定對您的載入 UI 更加精細,並將 Suspense 元件包裝在您的元件樹的較小或個別部分周圍
/**
* App.react.js
*/
const React = require('React');
const {Suspense} = require('React');
function App() {
return (
<>
{/* Show a separate loading UI for the LeftHandColumn */}
<Suspense fallback={<LeftColumnPlaceholder />}>
<LeftColumn />
</Suspense>
{/* Show a separate loading UI for both the Main and Secondary content */}
<Suspense fallback={<LoadingGlimmer />}>
<MainContent />
<SecondaryContent />
</Suspense>
</>
);
}
- 在這種情況下,我們顯示 2 個獨立的載入 UI
- 一個顯示直到
LeftColumn
準備好 - 另一個顯示直到
MainContent
和SecondaryContent
都準備好。
- 一個顯示直到
- 這樣做強大的地方在於,通過更精細地將我們的元件包裝在 Suspense 中,我們允許其他元件在它們準備好時更早呈現。在我們的範例中,通過在
Suspense
下單獨包裝MainContent
和SecondaryContent
,我們允許LeftColumn
在它準備好時立即呈現,這可能比內容部分準備好時更早。
暫停的轉換和更新
Suspense
邊界後備允許我們在最初呈現某些內容時描述我們的載入佔位符,但我們的應用程式也會在不同內容之間進行轉換。具體來說,當在已安裝的邊界內切換兩個元件時,您要切換到的新元件可能尚未載入其所有非同步依賴項,這意味著它也可能暫停。
在這種情況下,我們仍然會顯示 Suspense
邊界後備。但是,這意味著我們將隱藏現有內容,而改為顯示 Suspense
後備。在未來版本的 React 中,當支援並行呈現時,React 將提供一個選項來支援這種情況,並避免在暫停時使用 Suspense 後備隱藏已呈現的內容。
我們如何在 Relay 中使用 Suspense
查詢
在我們的案例中,我們的查詢元件是可以暫停的元件,因此我們使用 Suspense 來呈現在獲取查詢時的載入狀態。讓我們看看在實務中是什麼樣子
假設我們有以下查詢呈現器元件
/**
* MainContent.react.js
*
* Query Component
*/
const React = require('React');
const {graphql, usePreloadedQuery} = require('react-relay');
function MainContent(props) {
// Fetch and render a query
const data = usePreloadedQuery(
graphql`...`,
props.queryRef,
);
return (...);
}
/**
* App.react.js
*/
const React = require('React');
const {Suspense} = require('React');
function App() {
return (
// LoadingGlimmer is rendered via the Suspense fallback
<Suspense fallback={<LoadingGlimmer />}>
<MainContent /> {/* MainContent may suspend */}
</Suspense>
);
}
讓我們精煉一下這裡發生的事情
- 我們有一個
MainContent
元件,它是一個查詢呈現器,用於獲取和呈現查詢。當MainContent
嘗試獲取查詢時,它將暫停呈現,表示它尚未準備好呈現,並且它將在獲取查詢時解析。 - 包裝
MainContent
的Suspense
元件將檢測到MainContent
已暫停,並且將呈現fallback
元素(在本例中為LoadingGlimmer
),直到MainContent
準備好呈現;也就是說,直到獲取查詢為止。
片段
片段也與 Suspense 集成,以支援呈現 @defer
'd 的資料或 Relay Store 中部分可用的資料(即部分呈現)。
轉換
此外,我們用於重新獲取(刷新和重新獲取)和用於呈現連線的 API 也與 Suspense 集成;對於這些用例,這些 API 也會暫停。
此頁面是否有用?
請協助我們讓網站變得更好,方法是 回答幾個簡單的問題.