React Next Update:
Suspense for Date Fetching
&
Concurrent Mode
(最後在分享個小東西:useSound 🎺)
Ideas : Putting Research into Production
- 過多的 loading state,會讓我們覺得頁面切換變慢了!
- Concurrent Mode 提供 新的過場選擇(停留舊畫面)來避免這件事。
- Concurrent Mode 提供 新的過場選擇(停留舊畫面)來避免這件事。
- Hover 或 text input 需要在短時間內被快速處理,但是 clicks 和 頁面切換則可以等久一點也不會覺得lag !
- 我們心理上對於 Web 事件的不同期待,讓 React 決定實作「依照優先順序的render 」
在前端實作 Loading 和 排序資料顯示
Suspense for Date Fetching
Traditional Approach 1
- Render 後才去呼叫 API
-
會因為一層一層的 Render,造成抓資料時的 Waterfall
- 一個拉完後先顯示,再拉下一個在顯示剩下的。
- Loading時間都一樣久,一個跑完還要再等下一個。
// In a function component:
useEffect(() => {
fetchSomething();
}, []);
Traditional Approach 2
-
使用 GraphQL 的 Fragment,這樣你才能在 Render 前就知道 Component 需要什麼資料。
- 讓 Fragment 被 Compose 起來,就能避免抓資料時的 Waterfall。
- 資料是一次同時拉,但需要等所有資料都拉好才會一次顯示,不會先顯示拉好的東西,使用者可能會需要等一段時間。
read() → 拉完之後才會去讀資料
前兩種的資料都會有為 null 的狀態
// Start fetching early!
const resource = fetchProfileData();
// ...
function ProfileDetails() {
// Try to read user info
const user = resource.user.read();
return <h1>{user.name}</h1>;
}
Concurrent Mode
改善換頁體驗:換頁時暫留原本的畫面
先來介紹什麼是Transitions
Transition 就是指切換頁面的那個 Transition。
以官方提供的範例來說
Home Page 切到 Profile Page 時,
原本的畫面就不見了,只剩下一個大大的 Loading 😢。
The Three Steps of Transition
-
Default: Receded → Skeleton → Complete
- Receded → Taking a Step Back
-
Preferred: Pending → Skeleton → Complete
- Pending → Taking a Step forward
- Note : React will not stay in the Pending state for longer than necessary to avoid the Receded state.
- Pending → Taking a Step forward
How to do that !?
- 概念可用 Git branch 來理解。
-
startTransition 的 更新是在與現在這畫面不同的 branch
- isPending 讓我們知道那個 新畫面的 branch 正在準備
- 新畫面拉好後,我們現在的 branch 就會 merge 過去。
- 實際上不是同時 render 兩個東西,而是快速切換成兩者。
-
startTransition 的 更新是在與現在這畫面不同的 branch
在跳頁時,讓原本的畫面暫留一下子來跳過Loading State!
Origin
startTransition
Origin
🚨 isPending
Finished
NEW
useTransition
-
startTransition
-
Function,可以用來告訴 React 哪些 State Update 可以延後生效
-
-
isPending
-
Boolean ,代表 Transition 是否正在進行。
-
讓原先的頁面能顯示 Loading 提示,不然停在原本的頁面也會讓使用者以為網頁失去回應。
-
-
-
timeoutMs
-
Number,設定一個 Pending 的時間上限,超過了時間無論畫面有多糟都是直接進行 State Update ( Loading )。
-
- No useTransition vs useTransition
const [
startTransition,
isPending
] = useTransition({
timeoutMs: 10000
});
function handleClick() {
startTransition(() => {
onClick();
});
}
<>
<button
onClick={handleClick}
disabled={isPending}
>
{children}
</button>
{isPending ? spinner : null}
</>
Baking Transitions Into the Design System
Splitting High and Low Priority State
- 我們還可以直接把 Loading 包進 Components 中 → Button
-
Input 輸入時直接變 Loading
- ⚠️先維持一下原本的內容,UX更佳
- 運用 useTransition 來排序 setState
function handleChange(e) {
const value = e.target.value;
// Outside the transition (urgent)
setQuery(value);
startTransition(() => {
// Inside the transition (may be delayed)
setResource(fetchTranslation(value));
});
}
直接包成hook
import { useDeferredValue } from 'react';
const deferredValue = useDeferredValue(
value, { timeoutMs: 5000 // 延遲的毫秒數 });
Splitting High and Low Priority State
-
Input 輸入時直接變 Loading
- ⚠️先維持一下原本的內容,UX更佳
- 運用 useTransition 來排序 setState
function handleChange(e) {
const value = e.target.value;
// Outside the transition (urgent)
setQuery(value);
startTransition(() => {
// Inside the transition (may be delayed)
setResource(fetchTranslation(value));
});
}
Summary
-
改變前端讀取資料的方式
-
不只更改狀態,能更進一步去安排「更新的優先順序」
-
去除過多、冗長的 Loading 狀態
-
透過上述方式來 優化資料載入 和 頁面切換的體驗
功能對照:
(現在的版本已經變 Legacy Mode 了🥺)
外卡分享個有趣的小東西:useSound
1. Install
npm install use-sound
2. Finding and prepping sounds
3. Sound and accessibility
-
不能干擾到 Screen readers(視力受損的人常會用)
- Screen readers are pieces of software that parse the document and narrate its contents as sound.
-
Sites should remain 100% usable without sound.
- 以防聽力受損的人可能會聽不到重要資訊。
How to use?
const [play, exposedData] = useSound('xxx.mp3', HookOptions);
exposedData
- stop : function
- pause : function
- isPlaying : boolean
- duratin : Number (milliseconds)
HookOptions
- volume : 0 ~ 1
- playbackRate : 0.5 ~ 4
- slow down or speed up
- slow down or speed up
- interrupt : boolean
Demo
參考資料們:
useSound
By parkerhiphop
useSound
- 326