Reactã®experimental_SuspenseListã解説ïŒããŒãã£ã³ã°é åºã®å¶åŸ¡ãã³ã³ãã³ãã®åªå é äœä»ããããã¹ã ãŒãºãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã®äœææ¹æ³ããäŸãšå®è·µçãªã¢ããªã±ãŒã·ã§ã³ã§åŠã³ãŸãã
Unveiling React experimental_SuspenseList: Orchestrating Loading Sequences for Enhanced UX
Reactã®Suspense
ã³ã³ããŒãã³ãã¯ãããŒãã£ã³ã°ç¶æ
ã宣èšçã«åŠçããæ¹æ³ãæäŸããããŒã¿ã®ããŒããåŸ
æ©äžã«ãã©ãŒã«ããã¯UIã衚瀺ããããã»ã¹ãç°¡çŽ åããŸãããã ããè€æ°ã®Suspense
å¢çãæ±ãå Žåããããã解決ãããé åºã«ãã£ãŠããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ããããããããå ŽåããããŸããããã§experimental_SuspenseList
ãç»å ŽããŸããããã¯ããããã®å¢çã®ããŒãã£ã³ã°ã·ãŒã±ã³ã¹ã調æŽããéèŠãªã³ã³ãã³ããåªå
é äœä»ãããæçµçã«ããæŽç·ŽãããçŽæçãªãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãäœæããããã®åŒ·åãªããŒã«ã§ãã
What is experimental_SuspenseList
?
experimental_SuspenseList
ã¯ãReactã®å®éšçãªConcurrent Modeæ©èœã®ã³ã³ããŒãã³ãã§ããè€æ°ã®Suspense
ã³ã³ããŒãã³ããã©ãããããããã®ãã©ãŒã«ããã¯ã³ã³ãã³ãã衚瀺ããã³è§£æ±ºãããé åºãå¶åŸ¡ã§ããŸããããã¯ãéèŠåºŠã®äœãèŠçŽ ãããåã«éèŠãªã³ã³ãã³ããããŒããããããã«ããå Žåããããã¹ã ãŒãºã§èŠèŠçã«é
åçãªããŒãã£ã³ã°ãã©ã³ãžã·ã§ã³ãäœæããå Žåã«ç¹ã«åœ¹ç«ã¡ãŸãã
ãªãŒã±ã¹ãã©ãææ®ããææ®è
ã®ããã«èããŠãã ãããåSuspense
ã³ã³ããŒãã³ãã¯æ¥œåšã§ãããexperimental_SuspenseList
ã¯ãããã調åããŠæŒå¥ããããšãä¿èšŒããæ··æ²ãšãããŸãšãŸãã®ãªãããŒãã£ã³ã°ãšã¯ã¹ããªãšã³ã¹ãé²ããŸãã
Why Use experimental_SuspenseList
?
experimental_SuspenseList
ã䜿çšããäž»ãªå©ç¹ã以äžã«ç€ºããŸãã
- Prioritized Loading: éèŠãªã³ã³ãã³ããæåã«ããŒããããŠãŒã¶ãŒãæãéèŠãªæ å ±ãã§ããã ãæ©ãèŠãããããã«ããŸããããšãã°ãeã³ããŒã¹ãµã€ãã§ã¯ãé¢é£è£œåã衚瀺ããåã«ã補åã®ç»åãšèª¬æãããŒãããããšãæãŸããå ŽåããããŸãã
- Improved User Experience: ã¹ã ãŒãºãªããŒãã£ã³ã°ãã©ã³ãžã·ã§ã³ãäœæãããããããããèŠèŠçãªãžã£ã³ããåé¿ããŠãã¢ããªã±ãŒã·ã§ã³ã®å¿çæ§ãšæŽç·ŽåºŠãé«ããŸããããã·ã¥ããŒãã¢ããªã±ãŒã·ã§ã³ãæ³åããŠã¿ãŠãã ãããã³ã¢ã¡ããªãã¯ãæåã«ããŒãããããšã§ããŠãŒã¶ãŒã«ããã«äŸ¡å€ãæäŸããè£è¶³çãªãŠã£ãžã§ãããããã¯ã°ã©ãŠã³ãã§ããŒããããŸãã
- Controlled Loading Order:
Suspense
å¢çã解決ãããæ£ç¢ºãªé åºãå®çŸ©ããããŒãã£ã³ã°ã®é²è¡ç¶æ³ã«é¢ãããŠãŒã¶ãŒã®èªèã现ããå¶åŸ¡ã§ããŸãããã¥ãŒã¹Webãµã€ããæ€èšããŠãã ãããèšäºå šæã®åã«èŠåºããšç°¡åãªæŠèŠãããŒããããšããã©ãŠãžã³ã°ãšã¯ã¹ããªãšã³ã¹ãåäžããå¯èœæ§ããããŸãã - Reduced Perceived Latency: ããŒãã£ã³ã°ã·ãŒã±ã³ã¹ãæŠç¥çã«é åºä»ããããšã§ãåèšããŒãã£ã³ã°æéãåããŸãŸã§ãã£ãŠããã¢ããªã±ãŒã·ã§ã³ãããé«éã«æããããããšãã§ããŸããã¹ã±ã«ãã³UIã®åŸã«å®éã®ã³ã³ãã³ããããŒãããæ¹ãã空çœã®ç»é¢ã®åŸã«ãã¹ãŠãäžåºŠã«ããŒããããããéãæããããŸãã
How Does experimental_SuspenseList
Work?
experimental_SuspenseList
ã¯ãäž»ã«2ã€ã®propsãæäŸããããšã§æ©èœããŸãã
revealOrder
: ãã®propã¯ãåSuspense
ã³ã³ããŒãã³ãã衚瀺ãããé åºã決å®ããŸããæ¬¡ã®3ã€ã®å¯èœãªå€ãåãå ¥ããŸããforwards
: ã³ã³ããŒãã³ãããªãŒã«è¡šç€ºãããé åºïŒäžããäžïŒã§åã衚瀺ããŸããbackwards
: ã³ã³ããŒãã³ãããªãŒã«è¡šç€ºãããé åºãšã¯éã®é åºïŒäžããäžïŒã§åã衚瀺ããŸããtogether
: ãã¹ãŠã®åãåæã«è¡šç€ºãããã¹ãŠã®Suspense
ã³ã³ããŒãã³ãã解決ãããã®ãåŸ ã£ãŠããã³ã³ãã³ãã衚瀺ããŸãã
tail
: ãã®propã¯ãSuspense
ã³ã³ããŒãã³ããäžæããããšãã«ãæ®ãã®æªè¡šç€ºã®ã¢ã€ãã ãã©ã®ããã«åŠçããããå¶åŸ¡ããŸããæ¬¡ã®2ã€ã®å¯èœãªå€ãåãå ¥ããŸããcollapsed
: æ¬¡ã®æªè¡šç€ºã®ã¢ã€ãã ã®ãã©ãŒã«ããã¯ã®ã¿ã衚瀺ããŸããããã¯ãããã°ã¬ã¹ããŒã衚瀺ããå Žåã«åœ¹ç«ã¡ãŸããhidden
: æªè¡šç€ºã®ãã¹ãŠã®ã¢ã€ãã ã®ãã©ãŒã«ããã¯ãé衚瀺ã«ããŸããããã¯ãäžéããŒãã£ã³ã°ç¶æ ãªãã§ã¢ã€ãã ã1ã€ãã€è¡šç€ºããå Žåã«åœ¹ç«ã¡ãŸãã
Practical Examples
å®éã®ã·ããªãªã§experimental_SuspenseList
ãã©ã®ããã«äœ¿çšã§ãããã説æããããã«ãããã€ãã®å
·äœçãªäŸãèŠãŠã¿ãŸãããã
Example 1: Prioritizing Critical Content
æ¬¡ã®æ§é ãæã€ãŠãŒã¶ãŒãããã¡ã€ã«ããŒãžãæ³åããŠãã ããã
- User Avatar
- User Name
- User Bio
- User Recent Activity
- User Followers
æãéèŠãªæ
å ±ãæäŸãããŠãŒã¶ãŒã®ã¢ãã¿ãŒãååãããã³ç¥æŽãæåã«ããŒãããå¿
èŠããããŸããrevealOrder="forwards"
ã䜿çšããŠãexperimental_SuspenseList
ã䜿çšããŠãããå®çŸã§ããŸãã
<experimental_SuspenseList revealOrder="forwards">
<Suspense fallback={<p>Loading Avatar...</p>}>
<UserAvatar />
</Suspense>
<Suspense fallback={<p>Loading Name...</p>}>
<UserName />
</Suspense>
<Suspense fallback={<p>Loading Bio...</p>}>
<UserBio />
</Suspense>
<Suspense fallback={<p>Loading Activity...</p>}>
<UserRecentActivity />
</Suspense>
<Suspense fallback={<p>Loading Followers...</p>}>
<UserFollowers />
</Suspense>
</experimental_SuspenseList>
ãã®äŸã§ã¯ãã¢ãã¿ãŒãååãããã³ç¥æŽãæåã«ããŒãããããã®åŸã«æè¿ã®ã¢ã¯ãã£ããã£ãšãã©ãã¯ãŒãããŒããããŸããããã«ããããŠãŒã¶ãŒãæãéèŠãªæ å ±ããã°ãã確èªã§ããããã«ãªããŸãã
Example 2: Creating a Smooth Loading Transition
è€æ°ã®ãŠã£ãžã§ãããããŒãããããã·ã¥ããŒãã¢ããªã±ãŒã·ã§ã³ã«ã€ããŠèããŠã¿ãŸããrevealOrder="forwards"
ããã³tail="collapsed"
ã䜿çšããŠexperimental_SuspenseList
ã䜿çšãããšãããã°ã¬ã¹ããŒã䜿çšããŠã¹ã ãŒãºãªããŒãã£ã³ã°ãã©ã³ãžã·ã§ã³ãäœæã§ããŸãã
<experimental_SuspenseList revealOrder="forwards" tail="collapsed">
<Suspense fallback={<p>Loading Widget 1...</p>}>
<Widget1 />
</Suspense>
<Suspense fallback={<p>Loading Widget 2...</p>}>
<Widget2 />
</Suspense>
<Suspense fallback={<p>Loading Widget 3...</p>}>
<Widget3 />
</Suspense>
</experimental_SuspenseList>
ãã®å ŽåãåãŠã£ãžã§ããã¯é çªã«ããŒããããŸããtail="collapsed"
propã¯ã次ã«è¡šç€ºãããŠããªããŠã£ãžã§ããã®ãã©ãŒã«ããã¯ã®ã¿ã衚瀺ãããããã«ãããããå
šäœçãªããŒãã£ã³ã°ã®é²è¡ç¶æ³ã衚ãããã°ã¬ã¹ããŒãŸãã¯ããŒãã£ã³ã°ã€ã³ãžã±ãŒã¿ãŒã衚瀺ã§ããŸãã
Example 3: Loading Content in Reverse Order
ææ°ã®ã¡ãã»ãŒãžãæåã«ããŒããããã£ããã¢ããªã±ãŒã·ã§ã³ããããšããŸããrevealOrder="backwards"
ã䜿çšããŠexperimental_SuspenseList
ã䜿çšãããšããããå®çŸã§ããŸãã
<experimental_SuspenseList revealOrder="backwards">
<Suspense fallback={<p>Loading Message 3...</p>}>
<ChatMessage messageId={3} />
</Suspense>
<Suspense fallback={<p>Loading Message 2...</p>}>
<ChatMessage messageId={2} />
</Suspense>
<Suspense fallback={<p>Loading Message 1...</p>}>
<ChatMessage messageId={1} />
</Suspense>
</experimental_SuspenseList>
ããã«ãããæåã«messageId=3
ã®ChatMessage
ãããŒããããæ¬¡ã«messageId=2
ãæåŸã«messageId=1
ãããŒããããããããŠãŒã¶ãŒã¯ææ°ã®äŒè©±ãã§ããã ãæ©ã確èªã§ããŸãã
Global Considerations
ã°ããŒãã«ã³ã³ããã¹ãã§experimental_SuspenseList
ã䜿çšããå Žåã¯ã次ã®ç¹ãèæ
®ããããšãéèŠã§ãã
- Network Latency: ãããã¯ãŒã¯ã®é å»¶ã¯ãå°åã«ãã£ãŠå€§ããç°ãªãå ŽåããããŸããããŸããŸãªå Žæããã¢ããªã±ãŒã·ã§ã³ããã¹ãããŠãããŒãã£ã³ã°ã·ãŒã±ã³ã¹ãããŸããŸãªãããã¯ãŒã¯æ¡ä»¶ã«åãããŠæé©åãããŠããããšã確èªããŸããã³ã³ãã³ãé ä¿¡ãããã¯ãŒã¯ïŒCDNïŒã䜿çšããŠãããŸããŸãªå°ççå Žæã®ãŠãŒã¶ãŒã®é å»¶ãççž®ããããšãæ€èšããŠãã ããã
- Data Localization: ããŒã«ã©ã€ãºããå¿
èŠãããããŒã¿ïŒæ¥ä»ãæ°å€ãé貚ãªã©ïŒã衚瀺ããå Žåã¯ãããŒã«ã©ã€ãºããžãã¯ãå
Suspense
å¢çå ã§æ£ããé©çšãããŠããããšã確èªããŸããããšãã°ããšãŒããã圢åŒïŒDD / MM / YYYYïŒã§è¡šç€ºãããæ¥ä»ã¯ãç±³åœã®ãŠãŒã¶ãŒåãã«ç±³åœåœ¢åŒïŒMM / DD / YYYYïŒã«å€æããå¿ èŠãããå ŽåããããŸãã - Accessibility: ããŒãã£ã³ã°ãã©ãŒã«ããã¯ãé害ã®ãããŠãŒã¶ãŒã«ãã¢ã¯ã»ã¹ã§ããããšã確èªããŸããARIA屿§ã䜿çšããŠãããŒãã£ã³ã°ã®é²è¡ç¶æ³ãšããŒããããŠããã³ã³ãã³ãã«é¢ããæçãªæ å ±ãæäŸããŸããããšãã°ããã©ãŒã«ããã¯èŠçŽ ã§`aria-busy="true"`ã䜿çšããŸãã
- Internationalization (i18n): ãã©ãŒã«ããã¯ã¡ãã»ãŒãžãããŸããŸãªèšèªã«é©åã«ç¿»èš³ãããŠããããšã確èªããŠãã ãããããã¹ããã³ã³ããŒãã³ãã«çŽæ¥ããŒãã³ãŒãã£ã³ã°ããªãã§ãã ããã代ããã«ãi18nã©ã€ãã©ãªã䜿çšããŠç¿»èš³ã管çããŠãã ããã
- Right-to-Left (RTL) Layouts: ã¢ããªã±ãŒã·ã§ã³ãã¢ã©ãã¢èªãããã©ã€èªãªã©ã®RTLèšèªããµããŒãããŠããå Žåã¯ãããŒãã£ã³ã°ã·ãŒã±ã³ã¹ãšèŠèŠçãªãã©ã³ãžã·ã§ã³ãRTLã¬ã€ã¢ãŠãã«é©åã«é©åããŠããããšã確èªããŠãã ãããããã«ã¯ãUIå ã®èŠçŽ ã®é åºãéã«ããããã¢ãã¡ãŒã·ã§ã³ã調æŽããŠRTLã®æ¹åã«åãããããšãå«ãŸããå ŽåããããŸãã
Best Practices
experimental_SuspenseList
ã䜿çšããéã«çæãã¹ããã¹ããã©ã¯ãã£ã¹ã次ã«ç€ºããŸãã
- Keep it Simple: ããŒãã£ã³ã°ã·ãŒã±ã³ã¹ãè€éã«ããããªãã§ãã ãããæãéèŠãªã³ã³ãã³ããåªå é äœä»ãããã¹ã ãŒãºã§çŽæçãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãäœæããããšã«çŠç¹ãåœãŠãŠãã ããã
- Use Meaningful Fallbacks: ããŒããããŠããå 容ãæç¢ºã«ç€ºããæçã§èŠèŠçã«é åçãªãã©ãŒã«ããã¯ãæäŸããŸããã¹ã±ã«ãã³UIãŸãã¯ããã°ã¬ã¹ããŒã®äœ¿çšãæ€èšããŠãã ããã
- Test Thoroughly: ããŸããŸãªããã€ã¹ããã©ãŠã¶ãŒãããã³ãããã¯ãŒã¯æ¡ä»¶ã§ããŒãã£ã³ã°ã·ãŒã±ã³ã¹ããã¹ãããŠãæåŸ ã©ããã«æ©èœããããšã確èªããŸãã
- Consider Code Splitting:
experimental_SuspenseList
ãã³ãŒãåå²ãšçµã¿åãããŠãã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãããã«æé©åããŸããã³ãŒãåå²ã䜿çšãããšãç¹å®ã®ãã¥ãŒã«å¿ èŠãªã³ãŒãã®ã¿ãããŒãã§ãããããåæããŒãæéãççž®ããå šäœçãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãåäžãããããšãã§ããŸãã - Monitor Performance: ããã©ãŒãã³ã¹ç£èŠããŒã«ã䜿çšããŠãã³ã³ããŒãã³ãã®ããŒãæéã远跡ããæœåšçãªããã«ããã¯ãç¹å®ããŸãã
- Embrace the Experimental Nature:
experimental_SuspenseList
ã¯å®éšçãªæ©èœã§ããããã®APIã¯å°æ¥å€æŽãããå¯èœæ§ãããããšã«æ³šæããŠãã ãããææ°ã®ReactãªãªãŒã¹ãšããã¥ã¡ã³ãã§ææ°æ å ±ãå ¥æããŠãã ããã
Alternatives to experimental_SuspenseList
experimental_SuspenseList
ã¯ããŒãã£ã³ã°ã·ãŒã±ã³ã¹ã調æŽããããã®åŒ·åãªæ¹æ³ãæäŸããŸãããæ€èšã§ãã代æ¿ã¢ãããŒãããããŸãã
- Conditional Rendering: æ¡ä»¶ä»ãã¬ã³ããªã³ã°ã䜿çšãããšãã³ã³ããŒãã³ãã衚瀺ãããé åºãå¶åŸ¡ã§ããŸãããã®ã¢ãããŒãã¯
experimental_SuspenseList
ã䜿çšãããããç°¡åã§ããã倿°ã®ã³ã³ããŒãã³ããæ±ãå Žåã¯ç®¡çãè€éã«ãªãå¯èœæ§ããããŸãã - Custom Loading Indicators: ããŒãã£ã³ã°ãšã¯ã¹ããªãšã³ã¹ããã现ããå¶åŸ¡ã§ããã«ã¹ã¿ã ããŒãã£ã³ã°ã€ã³ãžã±ãŒã¿ãŒãäœæã§ããŸãããã®ã¢ãããŒãã¯
experimental_SuspenseList
ã䜿çšãããããæè»æ§ããããŸãããããå€ãã®æäœæ¥ãå¿ èŠã§ãã - Third-Party Libraries: é«åºŠãªããŒãã£ã³ã°ç®¡çæ©èœãæäŸãããµãŒãããŒãã£ã©ã€ãã©ãªãããã€ããããŸãããããã®ã©ã€ãã©ãªã¯ã
experimental_SuspenseList
ãããå æ¬çãªãœãªã¥ãŒã·ã§ã³ãæäŸã§ããŸãããã¢ããªã±ãŒã·ã§ã³ã«äœåãªãªãŒããŒãããã远å ããå¯èœæ§ããããŸãã
Conclusion
experimental_SuspenseList
ã¯ãããŒãã£ã³ã°ã·ãŒã±ã³ã¹ã調æŽããReactã¢ããªã±ãŒã·ã§ã³ã§ããã¹ã ãŒãºãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãäœæããããã®è²ŽéãªããŒã«ã§ããéèŠãªã³ã³ãã³ããåªå
é äœä»ãããããŒãã£ã³ã°é åºãå¶åŸ¡ããæçãªãã©ãŒã«ããã¯ãæäŸããããšã§ãã¢ããªã±ãŒã·ã§ã³ã®èªèãããããã©ãŒãã³ã¹ãšäœ¿ããããã倧å¹
ã«åäžãããããšãã§ããŸãããŸã å®éšçã§ãããReactã§ã®ããŒã¿ãã§ãããšã¬ã³ããªã³ã°ã®å°æ¥ãå£éèŠãããšãã§ããŸããã°ããŒãã«ã³ã³ããã¹ãã§experimental_SuspenseList
ã䜿çšããå Žåã¯ããããã¯ãŒã¯ã®é
å»¶ãããŒã¿ã®ããŒã«ã©ã€ãºãã¢ã¯ã»ã·ããªãã£ãªã©ã®ã°ããŒãã«ãªèŠå ãèæ
®ããããšãå¿ããªãã§ãã ããã
ãã®ããã°æçš¿ã§ç޹ä»ãããŠããæŠå¿µãšäŸãçè§£ããããšã§ãexperimental_SuspenseList
ã广çã«æŽ»çšããŠReactã¢ããªã±ãŒã·ã§ã³ã匷åããäžçäžã®ãŠãŒã¶ãŒã«åªãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸã§ããŸãã
Further Resources
- React Documentation: https://react.dev
- React Concurrent Mode: https://react.dev/blog/2022/03/29/react-v18
- Suspense for Data Fetching: https://react.dev/reference/react/Suspense