$30 off During Our Annual Pro Sale. View Details »

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

    View Slide

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

    View Slide

  3. ©2018 Wantedly, Inc.
    ࣗݾ঺հ
    ,PEBJ/BLBNVSB
    (JUIVC!LEOL
    5XJUUFS!LEOL@@
    4PGUXBSF&OHJOFFSBU8BOUFEMZ *OD৽ଔ
    +BWB4DSJQU 5ZQF4DSJQU 3FBDU 3BJMT 3VCZ

    View Slide

  4. ©2018 Wantedly, Inc.
    "QPMMPͰ3FBDU4VTQFOTF͕࢖͑Δʁ
    Page Title Page Subtitle

    View Slide

  5. ©2018 Wantedly, Inc.
    ࠓ೔͸"QPMMPͰ
    ඇಉظϨϯμϦϯά͕Ͱ͖Δ
    "TZOD.PEFͷ঺հͰ͢
    Page Title Page Subtitle

    View Slide

  6. ©2018 Wantedly, Inc.
    ໨࣍
    ‣3FBDU4VTQFOTF
    ‣"QPMMP$MJFOUͰ3FBDU4VTQFOTF

    View Slide

  7. ©2018 Wantedly, Inc.
    3FBDUl4VTQFOTFz
    Page Title Page Subtitle

    View Slide

  8. ©2018 Wantedly, Inc.
    React Suspense
    3FBDUl4VTQFOTFz
    ‣ ࠓ೥ͷ+4$POG*DFMBOEͰൃද͞Εͨ
    ‣ ͓ͦΒ͘SFBDUͰ͸࢖͑Δ
    ‣ ඇಉظΛ͍͍ײ͡ʹѻ͑Δ΋ͷ
    ‣ SFOEFS
    ͷதͰUISPXOFX1SPNJTF͢Δ

    View Slide

  9. ©2018 Wantedly, Inc.
    React Suspense
    ͳΜͰඞཁʁ
    ‣ 69ͷ޲্
    ‣ OFUXPSL؀ڥͷҧ͍ʹରԠ͢Δ
    4QJOOFS͕Ұॠ͚ͩදࣔ͞ΕΔ
    ը૾͕൒୺ͳঢ়ଶͰSFOEFS͞ΕΔ
    ‣ ࠓͩͱɺMPBEJOH͔Ͳ͏͔ͷνΣοΫΛ͢Δ

    View Slide

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

    View Slide

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

    View Slide

  12. ©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 Something went wrong.;
    }
    return this.props.children;
    }
    }



    ‣ ࢠίϯϙʔωϯτͷΤϥʔΛ਌ίϯϙʔωϯτͰ

    DBUDI͢Δ࢓૊Έ
    ‣ +4ͷDBUDIΈ͍ͨͳ͜ͱ͕$PNQPOFOUͰ

    Ͱ͖ΔΑ͏ʹͳΔ
    ‣ એݴతʹ͔͚Δ
    ‣ DPNQPOFOU%JE$BUDIͰัଊͰ͖Δ

    View Slide

  13. ©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 Something went wrong.;
    }
    return this.props.children;
    }
    }



    ‣ ࢠίϯϙʔωϯτͷΤϥʔΛ਌ίϯϙʔωϯτͰ

    DBUDI͢Δ࢓૊Έ
    ‣ +4ͷDBUDIΈ͍ͨͳ͜ͱ͕$PNQPOFOUͰ

    Ͱ͖ΔΑ͏ʹͳΔ
    ‣ એݴతʹ͔͚Δ
    ‣ DPNQPOFOU%JE$BUDIͰัଊͰ͖Δ

    View Slide

  14. ©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 Something went wrong.;
    }
    return this.props.children;
    }
    }



    ‣ ࢠίϯϙʔωϯτͷΤϥʔΛ਌ίϯϙʔωϯτͰ

    DBUDI͢Δ࢓૊Έ
    ‣ +4ͷDBUDIΈ͍ͨͳ͜ͱ͕$PNQPOFOUͰ

    Ͱ͖ΔΑ͏ʹͳΔ
    ‣ એݴతʹ͔͚Δ
    ‣ DPNQPOFOU%JE$BUDIͰัଊͰ͖Δ

    View Slide

  15. ©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 Something went wrong.;
    }
    return this.props.children;
    }
    }



    ‣ ࢠίϯϙʔωϯτͷΤϥʔΛ਌ίϯϙʔωϯτͰ

    DBUDI͢Δ࢓૊Έ
    ‣ +4ͷDBUDIΈ͍ͨͳ͜ͱ͕$PNQPOFOUͰ

    Ͱ͖ΔΑ͏ʹͳΔ
    ‣ એݴతʹ͔͚Δ
    ‣ DPNQPOFOU%JE$BUDIͰัଊͰ͖Δ

    View Slide

  16. ©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 (

    {results.slice(0, 5).map(result => {
    return (
    result={result}
    // ...
    />
    );
    })}

    );
    }

    View Slide

  17. ©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 (

    {results.slice(0, 5).map(result => {
    return (
    result={result}
    // ...
    />
    );
    })}

    );
    }

    View Slide

  18. ©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 (

    {results.slice(0, 5).map(result => {
    return (
    result={result}
    // ...
    />
    );
    })}

    );
    }

    View Slide

  19. ©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 (

    {results.slice(0, 5).map(result => {
    return (
    result={result}
    // ...
    />
    );
    })}

    );
    }

    View Slide

  20. ©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 (

    {results.slice(0, 5).map(result => {
    return (
    result={result}
    // ...
    />
    );
    })}

    );
    }
    ͜͜ͰDBDIF͔Βऔͬͯ͘Δ

    View Slide

  21. ©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 (

    {results.slice(0, 5).map(result => {
    return (
    result={result}
    // ...
    />
    );
    })}

    );
    }
    DBDIF͕ͳ͔ͬͨΒUISPXOFX1SPNJTF

    View Slide

  22. ©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͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔ͸ͣ

    View Slide

  23. ©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͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔ͸ͣ

    View Slide

  24. ©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͕ͳ͔ͬͨΒ͜Μͳײ͡ʹͳΔ͸ͣ

    View Slide

  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 (

    {didTimeout => (

    {children}
    {didTimeout ? fallback : null}

    )}

    );
    }
    export default Timeout;

    View Slide

  26. ©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 (

    {didTimeout => (

    {children}
    {didTimeout ? fallback : null}

    )}

    );
    }
    export default Timeout;

    View Slide

  27. ©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 (

    {didTimeout => (

    {children}
    {didTimeout ? fallback : null}

    )}

    );
    }
    export default Timeout;

    View Slide

  28. ©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 (

    {didTimeout => (

    {children}
    {didTimeout ? fallback : null}

    )}

    );
    }
    export default Timeout;

    View Slide

  29. ©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 (

    {didTimeout => (

    {children}
    {didTimeout ? fallback : null}

    )}

    );
    }
    export default Timeout;

    View Slide

  30. ©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 (

    {didTimeout => (

    {children}
    {didTimeout ? fallback : null}

    )}

    );
    }
    export default Timeout;

    View Slide

  31. ©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 (

    {didTimeout => (

    {children}
    {didTimeout ? fallback : null}

    )}

    );
    }
    export default Timeout;

    View Slide

  32. ©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 (

    {didTimeout => (

    {children}
    {didTimeout ? fallback : null}

    )}

    );
    }
    export default Timeout;

    View Slide

  33. ©2018 Wantedly, Inc.
    "QPMMP$MJFOUͰ΋Ͱ͖Δʁ
    Page Title Page Subtitle

    View Slide

  34. ©2018 Wantedly, Inc.
    React Suspense on Apollo
    "TZOD.PEF

    const Photo = ({ breed }) => (

    {({ data }) => {
    return ;
    }}

    );
    ‣ ͳΜͯݺͿ͔͸Θ͔Βͳ͍
    ‣ ࠷ॳ͸QSPQTͷ໊લ͕"TZD.PEFͩͬͨ
    ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠
    ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ
    ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕
    Ͱ͖Δ

    View Slide

  35. ©2018 Wantedly, Inc.
    React Suspense on Apollo
    const Photo = ({ breed }) => (

    {({ data }) => {
    return ;
    }}

    );
    ‣ ͳΜͯݺͿ͔͸Θ͔Βͳ͍
    ‣ ࠷ॳ͸QSPQTͷ໊લ͕"TZD.PEFͩͬͨ
    ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠
    ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ
    ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕
    Ͱ͖Δ
    "TZOD.PEF

    View Slide

  36. ©2018 Wantedly, Inc.
    React Suspense on Apollo
    const Photo = ({ breed }) => (

    {({ data }) => {
    return ;
    }}

    );
    const Photo = ({ breed }) => (

    {({ data, loading }) => {
    if (loading) return
    return ;
    }}

    );
    ‣ ͳΜͯݺͿ͔͸Θ͔Βͳ͍
    ‣ ࠷ॳ͸QSPQTͷ໊લ͕"TZD.PEFͩͬͨ
    ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠
    ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ
    ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕
    Ͱ͖Δ
    "TZOD.PEF

    View Slide

  37. ©2018 Wantedly, Inc.
    React Suspense on Apollo
    const Photo = ({ breed }) => (

    {({ data }) => {
    return ;
    }}

    );
    const Photo = ({ breed }) => (

    {({ data, loading }) => {
    if (loading) return
    return ;
    }}

    );
    ‣ ͳΜͯݺͿ͔͸Θ͔Βͳ͍
    ‣ ࠷ॳ͸QSPQTͷ໊લ͕"TZD.PEFͩͬͨ
    ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠
    ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ
    ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕
    Ͱ͖Δ
    "TZOD.PEF

    View Slide

  38. ©2018 Wantedly, Inc.
    React Suspense on Apollo
    const Photo = ({ breed }) => (

    {({ data }) => {
    return ;
    }}

    );

    {expired =>
    expired && selectedDog ? (

    ) : (

    )
    }

    ‣ ͳΜͯݺͿ͔͸Θ͔Βͳ͍
    ‣ ࠷ॳ͸QSPQTͷ໊લ͕"TZD.PEFͩͬͨ
    ‣ 3FBDU"QPMMPͰϦϦʔε͢ΔΒ͍͠
    ‣ "QPMMP$MJFOUͷ2VFSZ .VUBUJPOίϯ
    ϙʔωϯτͰ؆୯ʹඇಉظϨϯμϦϯά͕
    Ͱ͖Δ
    "TZOD.PEF

    View Slide

  39. ©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

    View Slide

  40. ©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

    View Slide

  41. ©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

    View Slide

  42. ©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

    View Slide

  43. ©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

    View Slide

  44. ©2018 Wantedly, Inc.
    ·ͱΊ
    ‣4VQFOTF͸3FBDUͰ࢖͑ΔΑ͏ʹͳΔ
    ‣"QPMMPͰͷ"TZOD3FOEFSJOH͸3FBDU"QPMMPͰ
    EFGFS4FU4UBUFΛ࢖ͬͨ-PX1SJPSJUZͱ͔΋࢖͑Δ
    ‣IUUQTDPEFTBOECPYJPT[LYWL͜͜Ͱ3FBDU4VTQFOTF৮ΕΔ
    ‣IUUQTDPEFTBOECPYJPTWKYM͜͜Ͱ"QPMMPͷ"TZODSFOEFSJOHΛ
    ৮ΕΔ

    View Slide