Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
React Suspense on Apollo
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Kodai Nakamura
August 02, 2018
Programming
1.6k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React Suspense on Apollo
Kodai Nakamura
August 02, 2018
More Decks by Kodai Nakamura
See All by Kodai Nakamura
React Fire
kdnk
2
1.5k
wejs24.pdf
kdnk
1
1.2k
Local State Management with Apollo
kdnk
2
1.6k
Other Decks in Programming
See All in Programming
夏だ!祭りだ!祭りとはドメインモデリングでは?
ryugen04
0
400
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
460
そこに3びきプロダクトがいるじゃろう——生成AI時代における“価値が届かない理由”の構造
kosuket
0
590
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.5k
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
260
異なる設計思想のフレームワークを経験して得た学び
amekuhideki
1
620
AWS DevOps AgentのAzure接続機能を検証して見えた活用法/Use Cases Verified for the AWS DevOps Agent's Azure Connectivity Feature
masakiokuda
1
270
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
5
530
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
170
FastAPI の並行処理モデルを完全に理解する
hoto17296
8
3k
書籍「プロフェッショナルAI駆動開発」紹介スライド
juntaromatsumoto
0
650
引き算の組織 ― アウトカムとAIに全振りするために辞めたこと ― / Organization by Subtraction
hirokiyamamoto14
PRO
0
300
Featured
See All Featured
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
380
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
6.1k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Abbi's Birthday
coloredviolet
3
9.5k
Typedesign – Prime Four
hannesfritz
42
3.1k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
220
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
250
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.4k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Transcript
©2018 Wantedly, Inc. React Suspense on Apollo Meguro.es #16 @
LIVESENSE 2nd.August.2018 - Kodai Nakamura
©2018 Wantedly, Inc. React Suspense on Apollo Meguro.es #16 @
LIVESENSE 2nd.August.2018 - Kodai Nakamura
©2018 Wantedly, Inc. ࣗݾհ ,PEBJ/BLBNVSB (JUIVC!LEOL 5XJUUFS!LEOL@@ 4PGUXBSF&OHJOFFSBU8BOUFEMZ *OD৽ଔ +BWB4DSJQU
5ZQF4DSJQU 3FBDU 3BJMT 3VCZ
©2018 Wantedly, Inc. "QPMMPͰ3FBDU4VTQFOTF͕͑Δʁ Page Title Page Subtitle
©2018 Wantedly, Inc. ࠓ"QPMMPͰ ඇಉظϨϯμϦϯά͕Ͱ͖Δ "TZOD.PEFͷհͰ͢ Page Title Page Subtitle
©2018 Wantedly, Inc. ࣍ ‣3FBDU4VTQFOTF ‣"QPMMP$MJFOUͰ3FBDU4VTQFOTF
©2018 Wantedly, Inc. 3FBDUl4VTQFOTFz Page Title Page Subtitle
©2018 Wantedly, Inc. React Suspense 3FBDUl4VTQFOTFz ‣ ࠓͷ+4$POG*DFMBOEͰൃද͞Εͨ ‣ ͓ͦΒ͘SFBDUͰ͑Δ
‣ ඇಉظΛ͍͍ײ͡ʹѻ͑Δͷ ‣ SFOEFS ͷதͰUISPXOFX1SPNJTF͢Δ
©2018 Wantedly, Inc. React Suspense ͳΜͰඞཁʁ ‣ 69ͷ্ ‣ OFUXPSLڥͷҧ͍ʹରԠ͢Δ
4QJOOFS͕Ұॠ͚ͩදࣔ͞ΕΔ ը૾͕ͳঢ়ଶͰSFOEFS͞ΕΔ ‣ ࠓͩͱɺMPBEJOH͔Ͳ͏͔ͷνΣοΫΛ͢Δ
©2018 Wantedly, Inc. React Suspense தͲ͏ͳͬͯΔʁ ‣ SFOEFSϝιουͷதͰDBDIF͔ΒΛऔಘ͢Δ ‣ DBDIF͕͋Δͱ͖ɺී௨ʹSFOEFS
‣ DBDIF͕ͳ͍ͱ͖ɺUISPXOFX1SPNJTF͢Δ 1SPNJTF͕SFTPMWF͞Ε͍ͯͳ͍߹SFOEFS͠ͳ͍ 1SPNJTF͕SFTPMWF͞ΕͨΒ࠶SFOEFS
©2018 Wantedly, Inc. React Suspense தͲ͏ͳͬͯΔʁ ‣ SFOEFSϝιουͷதͰDBDIF͔ΒΛऔಘ͢Δ ‣ DBDIF͕͋Δͱ͖ɺී௨ʹSFOEFS
‣ DBDIF͕ͳ͍ͱ͖ɺUISPXOFX1SPNJTF͢Δ 1SPNJTF͕SFTPMWF͞Ε͍ͯͳ͍߹SFOEFS͠ͳ͍ 1SPNJTF͕SFTPMWF͞ΕͨΒ࠶SFOEFS 1SPNJTFΛUISPX
©2018 Wantedly, Inc. React Suspense &SSPS#PVOEBSJFT class ErrorBoundary extends React.Component
{ constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { this.setState({ hasError: true }); logErrorToMyService(error, info); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } <ErrorBoundary> <MyWidget /> </ErrorBoundary> ‣ ࢠίϯϙʔωϯτͷΤϥʔΛίϯϙʔωϯτͰ DBUDI͢ΔΈ ‣ +4ͷDBUDIΈ͍ͨͳ͜ͱ͕$PNQPOFOUͰ Ͱ͖ΔΑ͏ʹͳΔ ‣ એݴతʹ͔͚Δ ‣ DPNQPOFOU%JE$BUDIͰัଊͰ͖Δ
©2018 Wantedly, Inc. React Suspense &SSPS#PVOEBSJFT class ErrorBoundary extends React.Component
{ constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { this.setState({ hasError: true }); logErrorToMyService(error, info); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } <ErrorBoundary> <MyWidget /> </ErrorBoundary> ‣ ࢠίϯϙʔωϯτͷΤϥʔΛίϯϙʔωϯτͰ DBUDI͢ΔΈ ‣ +4ͷDBUDIΈ͍ͨͳ͜ͱ͕$PNQPOFOUͰ Ͱ͖ΔΑ͏ʹͳΔ ‣ એݴతʹ͔͚Δ ‣ DPNQPOFOU%JE$BUDIͰัଊͰ͖Δ
©2018 Wantedly, Inc. React Suspense &SSPS#PVOEBSJFT class ErrorBoundary extends React.Component
{ constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { this.setState({ hasError: true }); logErrorToMyService(error, info); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } <ErrorBoundary> <MyWidget /> </ErrorBoundary> ‣ ࢠίϯϙʔωϯτͷΤϥʔΛίϯϙʔωϯτͰ DBUDI͢ΔΈ ‣ +4ͷDBUDIΈ͍ͨͳ͜ͱ͕$PNQPOFOUͰ Ͱ͖ΔΑ͏ʹͳΔ ‣ એݴతʹ͔͚Δ ‣ DPNQPOFOU%JE$BUDIͰัଊͰ͖Δ
©2018 Wantedly, Inc. React Suspense &SSPS#PVOEBSJFT class ErrorBoundary extends React.Component
{ constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { this.setState({ hasError: true }); logErrorToMyService(error, info); } render() { if (this.state.hasError) { return <h1>Something went wrong.</h1>; } return this.props.children; } } <ErrorBoundary> <MyWidget /> </ErrorBoundary> ‣ ࢠίϯϙʔωϯτͷΤϥʔΛίϯϙʔωϯτͰ DBUDI͢ΔΈ ‣ +4ͷDBUDIΈ͍ͨͳ͜ͱ͕$PNQPOFOUͰ Ͱ͖ΔΑ͏ʹͳΔ ‣ એݴతʹ͔͚Δ ‣ DPNQPOFOU%JE$BUDIͰัଊͰ͖Δ
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ import {createResource} from 'simple-cache-provider'; async function searchMovies(query) { const response = await fetch(/* URL */); return await response.json(); } const readMovieSearchResults = createResource(searchMovies); function Results(/* args */) { // ... const {results} = readMovieSearchResults(cache, query); return ( <div> {results.slice(0, 5).map(result => { return ( <Result result={result} // ... /> ); })} </div> ); }
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ import {createResource} from 'simple-cache-provider'; async function searchMovies(query) { const response = await fetch(/* URL */); return await response.json(); } const readMovieSearchResults = createResource(searchMovies); function Results(/* args */) { // ... const {results} = readMovieSearchResults(cache, query); return ( <div> {results.slice(0, 5).map(result => { return ( <Result result={result} // ... /> ); })} </div> ); }
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ import {createResource} from 'simple-cache-provider'; async function searchMovies(query) { const response = await fetch(/* URL */); return await response.json(); } const readMovieSearchResults = createResource(searchMovies); function Results(/* args */) { // ... const {results} = readMovieSearchResults(cache, query); return ( <div> {results.slice(0, 5).map(result => { return ( <Result result={result} // ... /> ); })} </div> ); }
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ import {createResource} from 'simple-cache-provider'; async function searchMovies(query) { const response = await fetch(/* URL */); return await response.json(); } const readMovieSearchResults = createResource(searchMovies); function Results(/* args */) { // ... const {results} = readMovieSearchResults(cache, query); return ( <div> {results.slice(0, 5).map(result => { return ( <Result result={result} // ... /> ); })} </div> ); }
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ import {createResource} from 'simple-cache-provider'; async function searchMovies(query) { const response = await fetch(/* URL */); return await response.json(); } const readMovieSearchResults = createResource(searchMovies); function Results(/* args */) { // ... const {results} = readMovieSearchResults(cache, query); return ( <div> {results.slice(0, 5).map(result => { return ( <Result result={result} // ... /> ); })} </div> ); } ͜͜ͰDBDIF͔Βऔͬͯ͘Δ
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ import {createResource} from 'simple-cache-provider'; async function searchMovies(query) { const response = await fetch(/* URL */); return await response.json(); } const readMovieSearchResults = createResource(searchMovies); function Results(/* args */) { // ... const {results} = readMovieSearchResults(cache, query); return ( <div> {results.slice(0, 5).map(result => { return ( <Result result={result} // ... /> ); })} </div> ); } DBDIF͕ͳ͔ͬͨΒUISPXOFX1SPNJTF
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ let cachedResults = null; const readMovieSearchResults = ({query}) => { if (cachedResults) { return cachedResults; } throw new Promise(async resolve => { const results = await searchMovies(query); cachedResults = results; resolve(); }); }; TJNQMFDBDIFQSPWJEFS͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔͣ
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ let cachedResults = null; const readMovieSearchResults = ({query}) => { if (cachedResults) { return cachedResults; } throw new Promise(async resolve => { const results = await searchMovies(query); cachedResults = results; resolve(); }); }; TJNQMFDBDIFQSPWJEFS͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔͣ
©2018 Wantedly, Inc. React Suspense TJNQMFDBDIFQSPWJEFS ‣ DBDIFΛ͍ͯ͠Δͱ͜Ζͷ࣮ ‣ GBDFCPPLSFBDUʹೖ͍ͬͯΔ
‣ ໊લͱ͔࣮ͱ͔มΘΔ͔ let cachedResults = null; const readMovieSearchResults = ({query}) => { if (cachedResults) { return cachedResults; } throw new Promise(async resolve => { const results = await searchMovies(query); cachedResults = results; resolve(); }); }; TJNQMFDBDIFQSPWJEFS͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔͣ
©2018 Wantedly, Inc. React Suspense 3FBDU5JNFPVU ‣ ·ͣEJE5JNFPVUGBMTFͰݺͼग़͞ΕΔ ‣ DIJMESFO͕SFOEFS͞ΕΔͱDBDIFݟʹߦ͘
‣ ଘࡏ͠ͳ͍ͱ͖ɺ1SPNJTF͕UISPX͞ΕΔ ‣ UISPXΛDBUDIͨ͠Βɺ͏Ұ࣮ߦ ‣ EJE5JNFPVUUSVFͱͳͬͯɺGBMMCBDL͕දࣔ͞ΕΔ ‣ 1SPNJTF͕SFTPMWF͢ΔͱEJE5JNFPVUGBMTF DIJMESFO͕SFOEFS͞ΕΔ import React, {Fragment} from 'react'; function Timeout({ms, fallback, children}) { return ( <React.Timeout ms={ms}> {didTimeout => ( <Fragment> <span hidden={didTimeout}>{children}</span> {didTimeout ? fallback : null} </Fragment> )} </React.Timeout> ); } export default Timeout;
©2018 Wantedly, Inc. React Suspense 3FBDU5JNFPVU ‣ ·ͣEJE5JNFPVUGBMTFͰݺͼग़͞ΕΔ ‣ DIJMESFO͕SFOEFS͞ΕΔͱDBDIFݟʹߦ͘
‣ ଘࡏ͠ͳ͍ͱ͖ɺ1SPNJTF͕UISPX͞ΕΔ ‣ UISPXΛDBUDIͨ͠Βɺ͏Ұ࣮ߦ ‣ EJE5JNFPVUUSVFͱͳͬͯɺGBMMCBDL͕දࣔ͞ΕΔ ‣ 1SPNJTF͕SFTPMWF͢ΔͱEJE5JNFPVUGBMTF DIJMESFO͕SFOEFS͞ΕΔ import React, {Fragment} from 'react'; function Timeout({ms, fallback, children}) { return ( <React.Timeout ms={ms}> {didTimeout => ( <Fragment> <span hidden={didTimeout}>{children}</span> {didTimeout ? fallback : null} </Fragment> )} </React.Timeout> ); } export default Timeout;
©2018 Wantedly, Inc. React Suspense 3FBDU5JNFPVU ‣ ·ͣEJE5JNFPVUGBMTFͰݺͼग़͞ΕΔ ‣ DIJMESFO͕SFOEFS͞ΕΔͱDBDIFݟʹߦ͘
‣ ଘࡏ͠ͳ͍ͱ͖ɺ1SPNJTF͕UISPX͞ΕΔ ‣ UISPXΛDBUDIͨ͠Βɺ͏Ұ࣮ߦ ‣ EJE5JNFPVUUSVFͱͳͬͯɺGBMMCBDL͕දࣔ͞ΕΔ ‣ 1SPNJTF͕SFTPMWF͢ΔͱEJE5JNFPVUGBMTF DIJMESFO͕SFOEFS͞ΕΔ import React, {Fragment} from 'react'; function Timeout({ms, fallback, children}) { return ( <React.Timeout ms={ms}> {didTimeout => ( <Fragment> <span hidden={didTimeout}>{children}</span> {didTimeout ? fallback : null} </Fragment> )} </React.Timeout> ); } export default Timeout;
©2018 Wantedly, Inc. React Suspense 3FBDU5JNFPVU ‣ ·ͣEJE5JNFPVUGBMTFͰݺͼग़͞ΕΔ ‣ DIJMESFO͕SFOEFS͞ΕΔͱDBDIFݟʹߦ͘
‣ ଘࡏ͠ͳ͍ͱ͖ɺ1SPNJTF͕UISPX͞ΕΔ ‣ UISPXΛDBUDIͨ͠Βɺ͏Ұ࣮ߦ ‣ EJE5JNFPVUUSVFͱͳͬͯɺGBMMCBDL͕දࣔ͞ΕΔ ‣ 1SPNJTF͕SFTPMWF͢ΔͱEJE5JNFPVUGBMTF DIJMESFO͕SFOEFS͞ΕΔ import React, {Fragment} from 'react'; function Timeout({ms, fallback, children}) { return ( <React.Timeout ms={ms}> {didTimeout => ( <Fragment> <span hidden={didTimeout}>{children}</span> {didTimeout ? fallback : null} </Fragment> )} </React.Timeout> ); } export default Timeout;
©2018 Wantedly, Inc. React Suspense 3FBDU5JNFPVU ‣ ·ͣEJE5JNFPVUGBMTFͰݺͼग़͞ΕΔ ‣ DIJMESFO͕SFOEFS͞ΕΔͱDBDIFݟʹߦ͘
‣ ଘࡏ͠ͳ͍ͱ͖ɺ1SPNJTF͕UISPX͞ΕΔ ‣ UISPXΛDBUDIͨ͠Βɺ͏Ұ࣮ߦ ‣ EJE5JNFPVUUSVFͱͳͬͯɺGBMMCBDL͕දࣔ͞ΕΔ ‣ 1SPNJTF͕SFTPMWF͢ΔͱEJE5JNFPVUGBMTF DIJMESFO͕SFOEFS͞ΕΔ import React, {Fragment} from 'react'; function Timeout({ms, fallback, children}) { return ( <React.Timeout ms={ms}> {didTimeout => ( <Fragment> <span hidden={didTimeout}>{children}</span> {didTimeout ? fallback : null} </Fragment> )} </React.Timeout> ); } export default Timeout;
©2018 Wantedly, Inc. React Suspense 3FBDU5JNFPVU ‣ ·ͣEJE5JNFPVUGBMTFͰݺͼग़͞ΕΔ ‣ DIJMESFO͕SFOEFS͞ΕΔͱDBDIFݟʹߦ͘
‣ ଘࡏ͠ͳ͍ͱ͖ɺ1SPNJTF͕UISPX͞ΕΔ ‣ UISPXΛDBUDIͨ͠Βɺ͏Ұ࣮ߦ ‣ EJE5JNFPVUUSVFͱͳͬͯɺGBMMCBDL͕දࣔ͞ΕΔ ‣ 1SPNJTF͕SFTPMWF͢ΔͱEJE5JNFPVUGBMTF DIJMESFO͕SFOEFS͞ΕΔ import React, {Fragment} from 'react'; function Timeout({ms, fallback, children}) { return ( <React.Timeout ms={ms}> {didTimeout => ( <Fragment> <span hidden={didTimeout}>{children}</span> {didTimeout ? fallback : null} </Fragment> )} </React.Timeout> ); } export default Timeout;
©2018 Wantedly, Inc. React Suspense 3FBDU5JNFPVU ‣ ·ͣEJE5JNFPVUGBMTFͰݺͼग़͞ΕΔ ‣ DIJMESFO͕SFOEFS͞ΕΔͱDBDIFݟʹߦ͘
‣ ଘࡏ͠ͳ͍ͱ͖ɺ1SPNJTF͕UISPX͞ΕΔ ‣ UISPXΛDBUDIͨ͠Βɺ͏Ұ࣮ߦ ‣ EJE5JNFPVUUSVFͱͳͬͯɺGBMMCBDL͕දࣔ͞ΕΔ ‣ 1SPNJTF͕SFTPMWF͢ΔͱEJE5JNFPVUGBMTFɻ DIJMESFO͕SFOEFS͞ΕΔ import React, {Fragment} from 'react'; function Timeout({ms, fallback, children}) { return ( <React.Timeout ms={ms}> {didTimeout => ( <Fragment> <span hidden={didTimeout}>{children}</span> {didTimeout ? fallback : null} </Fragment> )} </React.Timeout> ); } export default Timeout;
©2018 Wantedly, Inc. ‣ ·ͣEJE5JNFPVUGBMTFͰݺͼग़͞ΕΔ ‣ DIJMESFO͕SFOEFS͞ΕΔͱDBDIFݟʹߦ͘ ‣ ଘࡏ͠ͳ͍ͱ͖ɺ1SPNJTF͕UISPX͞ΕΔ ‣
UISPXΛDBUDIͨ͠ΒɺNTͬͯ͏Ұ࣮ߦ ‣ EJE5JNFPVUUSVFͱͳͬͯɺGBMMCBDL͕දࣔ͞ΕΔ ‣ 1SPNJTF͕SFTPMWF͢ΔͱEJE5JNFPVUGBMTFɻ DIJMESFO͕SFOEFS͞ΕΔ React Suspense 3FBDU5JNFPVU import React, {Fragment} from 'react'; function Timeout({ms, fallback, children}) { return ( <React.Timeout ms={ms}> {didTimeout => ( <Fragment> <span hidden={didTimeout}>{children}</span> {didTimeout ? fallback : null} </Fragment> )} </React.Timeout> ); } export default Timeout;
©2018 Wantedly, Inc. "QPMMP$MJFOUͰͰ͖Δʁ Page Title Page Subtitle
©2018 Wantedly, Inc. React Suspense on Apollo "TZOD.PEF const Photo
= ({ breed }) => ( <Query suspend query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data }) => { return <Image src={data.dog.displayImage} />; }} </Query> ); ‣ ͳΜͯݺͿ͔Θ͔Βͳ͍ ‣ ࠷ॳQSPQTͷ໊લ͕"TZD.PEFͩͬͨ ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠ ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕ Ͱ͖Δ
©2018 Wantedly, Inc. React Suspense on Apollo const Photo =
({ breed }) => ( <Query suspend query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data }) => { return <Image src={data.dog.displayImage} />; }} </Query> ); ‣ ͳΜͯݺͿ͔Θ͔Βͳ͍ ‣ ࠷ॳQSPQTͷ໊લ͕"TZD.PEFͩͬͨ ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠ ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕ Ͱ͖Δ "TZOD.PEF
©2018 Wantedly, Inc. React Suspense on Apollo const Photo =
({ breed }) => ( <Query suspend query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data }) => { return <Image src={data.dog.displayImage} />; }} </Query> ); const Photo = ({ breed }) => ( <Query query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data, loading }) => { if (loading) return <Loading /> return <Image src={data.dog.displayImage} />; }} </Query> ); ‣ ͳΜͯݺͿ͔Θ͔Βͳ͍ ‣ ࠷ॳQSPQTͷ໊લ͕"TZD.PEFͩͬͨ ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠ ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕ Ͱ͖Δ "TZOD.PEF
©2018 Wantedly, Inc. React Suspense on Apollo const Photo =
({ breed }) => ( <Query suspend query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data }) => { return <Image src={data.dog.displayImage} />; }} </Query> ); const Photo = ({ breed }) => ( <Query query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data, loading }) => { if (loading) return <Loading /> return <Image src={data.dog.displayImage} />; }} </Query> ); ‣ ͳΜͯݺͿ͔Θ͔Βͳ͍ ‣ ࠷ॳQSPQTͷ໊લ͕"TZD.PEFͩͬͨ ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠ ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕ Ͱ͖Δ "TZOD.PEF
©2018 Wantedly, Inc. React Suspense on Apollo const Photo =
({ breed }) => ( <Query suspend query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data }) => { return <Image src={data.dog.displayImage} />; }} </Query> ); <Timeout ms={2000}> {expired => expired && selectedDog ? ( <Loading /> ) : ( <Photo breed={selectedDog} /> ) } </Timeout> ‣ ͳΜͯݺͿ͔Θ͔Βͳ͍ ‣ ࠷ॳQSPQTͷ໊લ͕"TZD.PEFͩͬͨ ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠ ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕ Ͱ͖Δ "TZOD.PEF
©2018 Wantedly, Inc. React Suspense on Apollo Ͳ͏࣮ͬͯ͞Ε͍ͯΔ͔ class Query
extends React.Component { // ... render() { return this.props.children(this.getQueryResult(this.state)); } //... } private getQueryResult = ({queryObservable, evictData}) => { const currentResult = queryObservable!.currentResult(); const { loading, networkStatus, errors } = currentResult; if (loading) { if (this.props.suspend) { throw this.state.queryObservable!.result(); } Object.assign(data.data, this.previousData, currentResult.data); } else if (error) { // ... }; ‣ SFOEFSͷதͰHFU2VFSZ3FTVMU͕ݺΕ͍ͯΔ ‣ ͦͷதͰMPEJOHTVTQFOEͩͬͨΒ 1SPNJTFΛUISPX
©2018 Wantedly, Inc. React Suspense on Apollo Ͳ͏࣮ͬͯ͞Ε͍ͯΔ͔ class Query
extends React.Component { // ... render() { return this.props.children(this.getQueryResult(this.state)); } //... } private getQueryResult = ({queryObservable, evictData}) => { const currentResult = queryObservable!.currentResult(); const { loading, networkStatus, errors } = currentResult; if (loading) { if (this.props.suspend) { throw this.state.queryObservable!.result(); } Object.assign(data.data, this.previousData, currentResult.data); } else if (error) { // ... }; ‣ SFOEFSͷதͰHFU2VFSZ3FTVMU͕ݺΕ͍ͯΔ ‣ ͦͷதͰMPEJOHTVTQFOEͩͬͨΒ 1SPNJTFΛUISPX
©2018 Wantedly, Inc. React Suspense on Apollo Ͳ͏࣮ͬͯ͞Ε͍ͯΔ͔ class Query
extends React.Component { // ... render() { return this.props.children(this.getQueryResult(this.state)); } //... } private getQueryResult = ({queryObservable, evictData}) => { const currentResult = queryObservable!.currentResult(); const { loading, networkStatus, errors } = currentResult; if (loading) { if (this.props.suspend) { throw this.state.queryObservable!.result(); } Object.assign(data.data, this.previousData, currentResult.data); } else if (error) { // ... }; ‣ SFOEFSͷதͰHFU2VFSZ3FTVMU͕ݺΕ͍ͯΔ ‣ ͦͷதͰMPEJOHTVTQFOEͩͬͨΒ 1SPNJTFΛUISPX
©2018 Wantedly, Inc. React Suspense on Apollo Ͳ͏࣮ͬͯ͞Ε͍ͯΔ͔ class Query
extends React.Component { // ... render() { return this.props.children(this.getQueryResult(this.state)); } //... } private getQueryResult = ({queryObservable, evictData}) => { const currentResult = queryObservable!.currentResult(); const { loading, networkStatus, errors } = currentResult; if (loading) { if (this.props.suspend) { throw this.state.queryObservable!.result(); } Object.assign(data.data, this.previousData, currentResult.data); } else if (error) { // ... }; ‣ SFOEFSͷதͰHFU2VFSZ3FTVMU͕ݺΕ͍ͯΔ ‣ ͦͷதͰMPEJOHTVTQFOEͩͬͨΒ 1SPNJTFΛUISPX
©2018 Wantedly, Inc. React Suspense on Apollo Ͳ͏࣮ͬͯ͞Ε͍ͯΔ͔ class Query
extends React.Component { // ... render() { return this.props.children(this.getQueryResult(this.state)); } //... } private getQueryResult = ({queryObservable, evictData}) => { const currentResult = queryObservable!.currentResult(); const { loading, networkStatus, errors } = currentResult; if (loading) { if (this.props.suspend) { throw this.state.queryObservable!.result(); } Object.assign(data.data, this.previousData, currentResult.data); } else if (error) { // ... }; ‣ SFOEFSͷதͰHFU2VFSZ3FTVMU͕ݺΕ͍ͯΔ ‣ ͦͷதͰMPEJOHTVTQFOEͩͬͨΒ 1SPNJTFΛUISPX
©2018 Wantedly, Inc. ·ͱΊ ‣4VQFOTF3FBDUͰ͑ΔΑ͏ʹͳΔ ‣"QPMMPͰͷ"TZOD3FOEFSJOH3FBDU"QPMMPͰ EFGFS4FU4UBUFΛͬͨ-PX1SJPSJUZͱ͔͑Δ ‣IUUQTDPEFTBOECPYJPT[LYWL͜͜Ͱ3FBDU4VTQFOTF৮ΕΔ ‣IUUQTDPEFTBOECPYJPTWKYM͜͜Ͱ"QPMMPͷ"TZODSFOEFSJOHΛ
৮ΕΔ