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
AIだと陥りがちなJakarta EE最新技術への移行時の落とし穴と解決策
tnagao7
0
120
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
210
Signal Forms: Details & Live Coding @enterJS 2026 in Mannheim
manfredsteyer
PRO
0
170
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
260
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
130
ローカルLLMでどこまでコードが書けるか -拡張版 / How much code can be written on a local LLM Extended
kishida
11
4.3k
なぜ型を書くのか? TSKaigi2026で改めて考える #tskaigi_smarthr
kajitack
0
120
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
190
TypeScript+Orvalで実現する型安全かつ堅牢でスケーラブルなマルチチャネル通知基盤 / TSKaigi Night talks ~after conference~
d0riven
0
350
エージェンティックRAGにAWSで入門しよう!
har1101
8
1.7k
New "Type" system on PicoRuby
pocke
1
990
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.3k
Featured
See All Featured
Optimizing for Happiness
mojombo
378
71k
Git: the NoSQL Database
bkeepers
PRO
432
67k
The Limits of Empathy - UXLibs8
cassininazir
1
360
Deep Space Network (abreviated)
tonyrice
0
210
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
170
Exploring anti-patterns in Rails
aemeredith
3
420
Docker and Python
trallard
47
3.9k
The Spectacular Lies of Maps
axbom
PRO
1
820
For a Future-Friendly Web
brad_frost
183
10k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
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Λ
৮ΕΔ