Upgrade to Pro — share decks privately, control downloads, hide ads and more …

React Suspense on Apollo

React Suspense on Apollo

Kodai Nakamura

August 02, 2018
Tweet

More Decks by Kodai Nakamura

Other Decks in Programming

Transcript

  1. ©2018 Wantedly, Inc. React Suspense on Apollo Meguro.es #16 @

    LIVESENSE 2nd.August.2018 - Kodai Nakamura
  2. ©2018 Wantedly, Inc. React Suspense on Apollo Meguro.es #16 @

    LIVESENSE 2nd.August.2018 - Kodai Nakamura
  3. ©2018 Wantedly, Inc. React Suspense ͳΜͰඞཁʁ ‣ 69ͷ޲্ ‣ OFUXPSL؀ڥͷҧ͍ʹରԠ͢Δ

     4QJOOFS͕Ұॠ͚ͩදࣔ͞ΕΔ  ը૾͕൒୺ͳঢ়ଶͰSFOEFS͞ΕΔ ‣ ࠓͩͱɺMPBEJOH͔Ͳ͏͔ͷνΣοΫΛ͢Δ
  4. ©2018 Wantedly, Inc. React Suspense த਎͸Ͳ͏ͳͬͯΔʁ ‣ SFOEFSϝιουͷதͰ͸DBDIF͔Β஋Λऔಘ͢Δ ‣ DBDIF͕͋Δͱ͖͸ɺී௨ʹSFOEFS

    ‣ DBDIF͕ͳ͍ͱ͖͸ɺUISPXOFX1SPNJTF͢Δ  1SPNJTF͕SFTPMWF͞Ε͍ͯͳ͍৔߹͸SFOEFS͠ͳ͍  1SPNJTF͕SFTPMWF͞ΕͨΒ࠶SFOEFS
  5. ©2018 Wantedly, Inc. React Suspense த਎͸Ͳ͏ͳͬͯΔʁ ‣ SFOEFSϝιουͷதͰ͸DBDIF͔Β஋Λऔಘ͢Δ ‣ DBDIF͕͋Δͱ͖͸ɺී௨ʹSFOEFS

    ‣ DBDIF͕ͳ͍ͱ͖͸ɺUISPXOFX1SPNJTF͢Δ  1SPNJTF͕SFTPMWF͞Ε͍ͯͳ͍৔߹͸SFOEFS͠ͳ͍  1SPNJTF͕SFTPMWF͞ΕͨΒ࠶SFOEFS 1SPNJTFΛUISPX 
  6. ©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ͰัଊͰ͖Δ
  7. ©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ͰัଊͰ͖Δ
  8. ©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ͰัଊͰ͖Δ
  9. ©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ͰัଊͰ͖Δ
  10. ©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> ); }
  11. ©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> ); }
  12. ©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> ); }
  13. ©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> ); }
  14. ©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͔Βऔͬͯ͘Δ
  15. ©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
  16. ©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͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔ͸ͣ
  17. ©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͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔ͸ͣ
  18. ©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͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔ͸ͣ
  19. ©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;
  20. ©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;
  21. ©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;
  22. ©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;
  23. ©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;
  24. ©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;
  25. ©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;
  26. ©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;
  27. ©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ίϯ ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕ Ͱ͖Δ
  28. ©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
  29. ©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
  30. ©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
  31. ©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
  32. ©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
  33. ©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
  34. ©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
  35. ©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
  36. ©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