Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save vivek12345/4869f20a4df2c83a5cd9eb751dcc8312 to your computer and use it in GitHub Desktop.

Select an option

Save vivek12345/4869f20a4df2c83a5cd9eb751dcc8312 to your computer and use it in GitHub Desktop.

Revisions

  1. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 2 additions and 0 deletions.
    Original file line number Diff line number Diff line change
    @@ -390,6 +390,8 @@ What are your thoughts on these features? Let me know in the comments section!
    Here is the roadmap from the React team for the upcoming releases:<br>
    [https://reactjs.org/blog/2018/11/27/react-16-roadmap.html](https://reactjs.org/blog/2018/11/27/react-16-roadmap.html)

    Big thanks to [Sara Vieira](https://twitter.com/NikkitaFTW) for reviewing this article and suggesting improvements in it.

    ### **Resources**

    - [React lazy, Suspense and Concurrent React Breakdown with
  2. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 2 additions and 0 deletions.
    Original file line number Diff line number Diff line change
    @@ -270,6 +270,8 @@ Wrap strict mode around your app like so:
    This is the kind of stuff it allows you to do:

    https://twitter.com/acdlite/status/954798592320942081

    ---

    To use this we need another **unstable** api which is part of an **npm** package
  3. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 1 addition and 1 deletion.
    Original file line number Diff line number Diff line change
    @@ -356,7 +356,7 @@ function App() {

    **Note**: With this approach, **RestaurantListComponent** will be a code splitted component loaded on demand.

    ![](https://i.imgur.com/YK46ZFA.gif)
    https://imgur.com/YK46ZFA
    <span class="figcaption_hack">Example of lazily loaded component in a chunk “**1.chunk.js”**</span>

    ---
  4. vivek12345 revised this gist Jan 20, 2019. No changes.
  5. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 1 addition and 1 deletion.
    Original file line number Diff line number Diff line change
    @@ -356,7 +356,7 @@ function App() {

    **Note**: With this approach, **RestaurantListComponent** will be a code splitted component loaded on demand.

    ![](https://i.imgur.com/YK46ZFA.gifv)
    ![](https://i.imgur.com/YK46ZFA.gif)
    <span class="figcaption_hack">Example of lazily loaded component in a chunk “**1.chunk.js”**</span>

    ---
  6. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 1 addition and 4 deletions.
    Original file line number Diff line number Diff line change
    @@ -270,8 +270,6 @@ Wrap strict mode around your app like so:
    This is the kind of stuff it allows you to do:

    <video preload="none" playsinline="" poster="https://pbs.twimg.com/ext_tw_video_thumb/954798539476942848/pu/img/BNb4xgh-pl_H3gbO.jpg" src="blob:https://twitter.com/ecc06669-70be-4f9b-bb21-2575be961e92" style="width: 100%; height: 100%; position: absolute; background-color: black; transform: rotate(0deg) scale(1.005);"></video>

    ---

    To use this we need another **unstable** api which is part of an **npm** package
    @@ -356,8 +354,7 @@ function App() {
    }
    ```

    **Note**: With this approach, **RestaurantListComponent **will be a code
    splitted component loaded on demand.
    **Note**: With this approach, **RestaurantListComponent** will be a code splitted component loaded on demand.

    ![](https://i.imgur.com/YK46ZFA.gifv)
    <span class="figcaption_hack">Example of lazily loaded component in a chunk “**1.chunk.js”**</span>
  7. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 2 additions and 2 deletions.
    Original file line number Diff line number Diff line change
    @@ -270,7 +270,7 @@ Wrap strict mode around your app like so:
    This is the kind of stuff it allows you to do:

    ![](https://i.imgur.com/YK46ZFA.gifv)
    <video preload="none" playsinline="" poster="https://pbs.twimg.com/ext_tw_video_thumb/954798539476942848/pu/img/BNb4xgh-pl_H3gbO.jpg" src="blob:https://twitter.com/ecc06669-70be-4f9b-bb21-2575be961e92" style="width: 100%; height: 100%; position: absolute; background-color: black; transform: rotate(0deg) scale(1.005);"></video>

    ---

    @@ -359,7 +359,7 @@ function App() {
    **Note**: With this approach, **RestaurantListComponent **will be a code
    splitted component loaded on demand.

    ![](https://cdn-images-1.medium.com/max/1600/1*eUDG6xBLoo7Vcmvq-hyUQw.gif)
    ![](https://i.imgur.com/YK46ZFA.gifv)
    <span class="figcaption_hack">Example of lazily loaded component in a chunk “**1.chunk.js”**</span>

    ---
  8. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 4 additions and 4 deletions.
    Original file line number Diff line number Diff line change
    @@ -66,10 +66,10 @@ For example:

    In the above example we can have 4 api calls:<br>

    1. **<RestaurantInfo />** component making one api call for getting basic information about a Restaurant<br>
    2. **<RestaurantAlbums />** api to fetch all the images of that Restaurant<br>
    3. **<RestaurantReviews />** api to fetch all reviews<br>
    4. **<RestaurantReviewDetail />** api to fetch some details around those individual reviews like comments, likes etc.
    1. **RestaurantInfo** component making one api call for getting basic information about a Restaurant<br>
    2. **RestaurantAlbums** api to fetch all the images of that Restaurant<br>
    3. **RestaurantReviews** api to fetch all reviews<br>
    4. **RestaurantReviewDetail** api to fetch some details around those individual reviews like comments, likes etc.

    The problem with the above code structure is that we need to somehow manage the
    loading state and data fetching states for all those api calls that are
  9. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 18 additions and 14 deletions.
    32 changes: 18 additions & 14 deletions Magic of React Suspense with concurrent react and React.lazy API.md
    Original file line number Diff line number Diff line change
    @@ -51,7 +51,7 @@ The answer to that is yes it’s still possible to use loading state and play
    around with it to show/hide the spinner but as the application grows complex
    this becomes tedious to manage.

    For example:-
    For example:

    <RestaurantDetail>
    <RestaurantInfo />
    @@ -106,7 +106,7 @@ Now a word of caution, `react-cache` is still unstable and it’s implementation
    or api might change over time.

    An example of how to use react-cache to create a restaurant list fetching
    resource:-
    resource:

    ```
    import {
    @@ -137,10 +137,9 @@ name suggests this is still `unstable`
    > the hash map which caches the data.
    The whole suspense and suspended rendering magic comes into play with this
    **unstable_createResource** because this function** throws a promise.**
    **unstable_createResource** because this function **throws a promise.**

    ![https://twitter.com/dan_abramov/status/970758867779977217](https://imgur.com/Iyp5pRK.png)
    <span class="figcaption_hack">Dan’s tweet about cache throwing a promise and react catching it</span>

    A layman implementation of what it might look like could be:

    @@ -164,15 +163,15 @@ a param which is usually the hash key of the hash map and if the data is not
    fetched yet then this read function will **throw a promise** as we see on line
    no 6.

    The actual implementation of this function can be found here:-
    The actual implementation of this function can be found here:

    [https://github.com/facebook/react/blob/master/packages/react-cache/src/ReactCache.js#L142](https://github.com/facebook/react/blob/master/packages/react-cache/src/ReactCache.js#L142)

    ---

    **Who will catch this promise?**

    **Error Boundaries **will catch this promise like how they used to catch the
    **Error Boundaries** will catch this promise like how they used to catch the
    error thrown by React render.<br> More information on Error Boundaries can be
    found on reactjs.org:<br>
    [https://reactjs.org/docs/error-boundaries.html](https://reactjs.org/docs/error-boundaries.html)
    @@ -236,7 +235,7 @@ We do this for concurrent React:

    That is all that needs to be changed to enable Concurrent React.

    This brings us with a new magical capability which is:-
    This brings us with a new magical capability which is:

    - `maxDuration` prop- this is the time in **ms** after which our fallback
    component will show up. This will avoid screen flickering issue which usually
    @@ -271,6 +270,8 @@ Wrap strict mode around your app like so:
    This is the kind of stuff it allows you to do:

    ![](https://i.imgur.com/YK46ZFA.gifv)

    ---

    To use this we need another **unstable** api which is part of an **npm** package
    @@ -283,7 +284,6 @@ showing the detail page until the data for that page is loaded.

    ```
    import { unstable_scheduleCallback as defer } from "scheduler";
    ...
    toggleDetailPage = id => {
    if (id) {
    @@ -317,16 +317,13 @@ Here is what Dan had to say about this whole set state defer:

    ---

    ### \*\*Code Splitting with

    **[React.lazy](https://reactjs.org/docs/code-splitting.html)** and
    React.Suspense\*\*
    ### **Code Splitting with [React.lazy](https://reactjs.org/docs/code-splitting.html) and React.Suspense**

    <br>

    > The React.lazy function lets you render a dynamic import as a regular component.
    Before:
    **Before:**

    ```
    import React from 'react';
    @@ -344,7 +341,7 @@ function App() {
    **Note**: In the above implementation the **RestaurantListComponent** will be
    part of your main bundle and will not be lazy-loaded.

    After:
    **After:**

    ```
    import React, { Suspense, lazy } from 'react';
    @@ -376,6 +373,13 @@ splitted component loaded on demand.

    - react-cache and scheduler are unstable. Here is how you can still use them:

    ```
    npm install [email protected] - next
    npm install [email protected] - next
    npm install [email protected]
    npm install [email protected]
    ```

    ---

    ### **Conclusion**
  10. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 3 additions and 3 deletions.
    Original file line number Diff line number Diff line change
    @@ -139,7 +139,7 @@ name suggests this is still `unstable`
    The whole suspense and suspended rendering magic comes into play with this
    **unstable_createResource** because this function** throws a promise.**

    ![https://twitter.com/dan_abramov/status/970758867779977217](https://imgur.com/Iyp5pRK)
    ![https://twitter.com/dan_abramov/status/970758867779977217](https://imgur.com/Iyp5pRK.png)
    <span class="figcaption_hack">Dan’s tweet about cache throwing a promise and react catching it</span>

    A layman implementation of what it might look like could be:
    @@ -244,7 +244,7 @@ This brings us with a new magical capability which is:-
    comes immediately. This will make sure that for faster networks Spinner will
    never show up thereby avoiding screen flickering.

    ![https://twitter.com/dan_abramov/status/1040056722604417025](https://imgur.com/09Ry0aC)
    ![https://twitter.com/dan_abramov/status/1040056722604417025](https://imgur.com/09Ry0aC.png)

    ---

    @@ -313,7 +313,7 @@ can be found here<br>

    Here is what Dan had to say about this whole set state defer:

    ![https://twitter.com/dan_abramov/status/970363904319741952](https://imgur.com/UTVzgth)
    ![https://twitter.com/dan_abramov/status/970363904319741952](https://imgur.com/UTVzgth.png)

    ---

  11. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 0 additions and 2 deletions.
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,5 @@
    ### Magic of React Suspense with concurrent react and React.lazy API

    <span class="figcaption_hack">Magical land of React Suspense, Concurrent React and React.lazy API</span>

    [Dan Abramov](https://twitter.com/dan_abramov) in his talk “[Beyond React
    16](https://www.youtube.com/watch?v=nLF0n9SACd4)” at JSConf Iceland 2018 said:

  12. vivek12345 revised this gist Jan 20, 2019. 1 changed file with 178 additions and 68 deletions.
    246 changes: 178 additions & 68 deletions Magic of React Suspense with concurrent react and React.lazy API.md
    Original file line number Diff line number Diff line change
    @@ -1,13 +1,12 @@
    ### Magic of React Suspense with concurrent react and React.lazy API

    ![](https://cdn-images-1.medium.com/max/1600/1*LjRa4DHzTkRCIjGmz1tgjQ.jpeg)
    <span class="figcaption_hack">Magical land of React Suspense, Concurrent React and React.lazy API</span>

    [Dan Abramov](https://twitter.com/dan_abramov) in his talk “[Beyond React
    16](https://www.youtube.com/watch?v=nLF0n9SACd4)” at JSConf Iceland 2018 said:

    > *We’ve built a generic way to ensure that high-priority updates like user input
    > don’t get blocked by rendering low-priority updates.*
    > _We’ve built a generic way to ensure that high-priority updates like user input
    > don’t get blocked by rendering low-priority updates._
    Let’s understand what this means and also get introduced to some of the new
    features coming to React, some of which have been released as part of the latest
    @@ -16,20 +15,20 @@ possible that the implementation of the api might change over time.

    Things we got introduced to in the talk:

    * [Suspense](https://reactjs.org/docs/code-splitting.html)
    * [react-cache](https://www.npmjs.com/package/react-cache)
    * Defer set state with [scheduler](https://www.npmjs.com/package/scheduler)
    * Concurrent React Mode
    * Code splitting with [React.lazy](https://reactjs.org/docs/code-splitting.html)
    - [Suspense](https://reactjs.org/docs/code-splitting.html)
    - [react-cache](https://www.npmjs.com/package/react-cache)
    - Defer set state with [scheduler](https://www.npmjs.com/package/scheduler)
    - Concurrent React Mode
    - Code splitting with [React.lazy](https://reactjs.org/docs/code-splitting.html)

    *****
    ---

    ### **Suspense**

    > React.Suspense in simple words means we can suspend the rendering of our
    > component or components until some condition is met( for example data from an
    endpoint or a resource is loaded) and until then show a fallback(for-example a
    spinner)
    > endpoint or a resource is loaded) and until then show a fallback(for-example a
    > spinner)
    **Why do we need this?**

    @@ -67,13 +66,12 @@ For example:-
    </RestaurantReviews>
    </RestaurantDetail>

    In the above example we can have 4 api calls:<br> 1) **<RestaurantInfo />**
    component making one api call for getting basic information about a Restaurant
    In the above example we can have 4 api calls:<br>

    2) **<RestaurantAlbums />** api to fetch all the images of that Restaurant<br>
    3) **<RestaurantReviews />** api to fetch all reviews<br> 4)
    **<RestaurantReviewDetail />** api to fetch some details around those individual
    reviews like comments, likes etc.
    1. **<RestaurantInfo />** component making one api call for getting basic information about a Restaurant<br>
    2. **<RestaurantAlbums />** api to fetch all the images of that Restaurant<br>
    3. **<RestaurantReviews />** api to fetch all reviews<br>
    4. **<RestaurantReviewDetail />** api to fetch some details around those individual reviews like comments, likes etc.

    The problem with the above code structure is that we need to somehow manage the
    loading state and data fetching states for all those api calls that are
    @@ -83,16 +81,16 @@ happening above.

    For the above problem we have multiple solutions which can be as follows:

    * Delegate all api calling logic into the parent container and let all of them
    wait until all data fetching is complete and pass data to child components as
    props. The problem with this approach is now the parent needs to be aware of all
    api calls which are needed by child components and also maintain a complex state
    for all these api responses.
    * Make all the child components smart/stateful components and let each of them
    manage their own **loading** and **data** states. This is complex since
    converting a stateless component to a stateful component is not something we
    would want to do.
    * The third solution is using **Suspense**
    - Delegate all api calling logic into the parent container and let all of them
    wait until all data fetching is complete and pass data to child components as
    props. The problem with this approach is now the parent needs to be aware of all
    api calls which are needed by child components and also maintain a complex state
    for all these api responses.
    - Make all the child components smart/stateful components and let each of them
    manage their own **loading** and **data** states. This is complex since
    converting a stateless component to a stateful component is not something we
    would want to do.
    - The third solution is using **Suspense**

    **With Suspense it works differently. How?**

    @@ -112,24 +110,57 @@ or api might change over time.
    An example of how to use react-cache to create a restaurant list fetching
    resource:-

    *****
    ```
    import {
    unstable_createResource,
    } from "react-cache";
    const restaurantListResource = unstable_createResource(() => {
    return new Promise((resolve, reject) => {
    fetch("https://8kq2vljq58.sse.codesandbox.io/restaurants")
    .then(res => res.json())
    .then(response => {
    const { restaurants } = response;
    resolve(restaurants);
    });
    });
    });
    ```

    ---

    ### **react-cache**

    In the above code snippet we are using **unstable_createResource** and as the
    name suggests this is still `unstable`
    name suggests this is still `unstable`

    > unstable_createResource takes a **function** as one of its arguments and a
    > **hash** **function** as the second argument which is used to create the key for
    the hash map which caches the data.
    > the hash map which caches the data.
    The whole suspense and suspended rendering magic comes into play with this
    **unstable_createResource** because this function** throws a promise.**

    ![https://twitter.com/dan_abramov/status/970758867779977217](https://imgur.com/Iyp5pRK)
    <span class="figcaption_hack">Dan’s tweet about cache throwing a promise and react catching it</span>

    A layman implementation of what it might look like could be:

    ```
    const unstable_createResource = (method) => {
    let resolved = new Map();
    return {
    read(key) => {
    if (!resolved.has(key)) {
    throw method(...args)
    .then(val => resolved.set(key, val));
    }
    return resolved.get(key);
    }
    };
    }
    ```

    If you notice, it returns an object with a `read` function which takes `key` as
    a param which is usually the hash key of the hash map and if the data is not
    fetched yet then this read function will **throw a promise** as we see on line
    @@ -139,7 +170,7 @@ The actual implementation of this function can be found here:-

    [https://github.com/facebook/react/blob/master/packages/react-cache/src/ReactCache.js#L142](https://github.com/facebook/react/blob/master/packages/react-cache/src/ReactCache.js#L142)

    *****
    ---

    **Who will catch this promise?**

    @@ -151,20 +182,46 @@ found on reactjs.org:<br>
    So now with **unstable_createResource** our **RestaurantList** component would
    look something like this:

    *****
    ```
    const RestaurantList = () => {
    // if no restaurants are found in the cache, the suspense will throw a promise
    const restaurants = restaurantListResource.read();
    // this line will have to wait until that promise resolves
    return (
    <article>
    <h2 className="f3 fw4 pa3 mv0">Restaurant List</h2>
    <div className="cf pa2">{renderRestaurants(restaurants)}</div>
    </article>
    );
    };
    ```

    ---

    **Who will implement componentDidCatch?**

    This is where **Suspense** from react comes into play. **React.Suspense** has a
    **componentDidCatch** sort of mechanism which will catch this promise and show a
    fallback until the promise is resolved.

    ```
    import React, { Suspense } from 'react';
    const RestaurantListContainer = props => {
    return (
    <Suspense fallback={'Loading...'}>
    <RestaurantList />
    </Suspense>
    );
    };
    ```

    This concludes the topic of using React.Suspense to suspend rendering until data
    fetching is complete and until then show a fallback. We learnt about
    **react-cache** in this topic and how it can be used to throw a promise and
    suspend rendering.
    suspend rendering.

    *****
    ---

    ### **Concurrent React**

    @@ -183,13 +240,15 @@ That is all that needs to be changed to enable Concurrent React.

    This brings us with a new magical capability which is:-

    * `maxDuration` prop- this is the time in **ms** after which our fallback
    component will show up. This will avoid screen flickering issue which usually
    occurs on faster network where the loader shows up for few ms and then the data
    comes immediately. This will make sure that for faster networks Spinner will
    never show up thereby avoiding screen flickering.
    - `maxDuration` prop- this is the time in **ms** after which our fallback
    component will show up. This will avoid screen flickering issue which usually
    occurs on faster network where the loader shows up for few ms and then the data
    comes immediately. This will make sure that for faster networks Spinner will
    never show up thereby avoiding screen flickering.

    ![https://twitter.com/dan_abramov/status/1040056722604417025](https://imgur.com/09Ry0aC)

    *****
    ---

    #### React.StrictMode

    @@ -203,28 +262,50 @@ Wrap strict mode around your app like so:
    <App />
    , document.getElementById('root'));

    *****
    ---

    ### **Defer Mode in Concurrent React**

    > We can defer certain setState calls and let it wait until some other important
    > operations like data fetching finishes for example clicking on a restaurant card
    and not rendering the detail page until all the data for the detail page has
    been loaded.
    > and not rendering the detail page until all the data for the detail page has
    > been loaded.
    This is the kind of stuff it allows you to do:

    *****
    ---

    To use this we need another **unstable** api which is part of an **npm** package
    called as `scheduler`

    import { unstable_scheduleCallback as defer } from "
    ";
    import { unstable_scheduleCallback as defer } from "scheduler";

    To defer a setState call we can do like the function below where I am delaying
    showing the detail page until the data for that page is loaded.

    ```
    import { unstable_scheduleCallback as defer } from "scheduler";
    ...
    toggleDetailPage = id => {
    if (id) {
    this.setState({
    id: id
    });
    defer(() => {
    this.setState({
    showDetail: true
    });
    });
    } else {
    this.setState({
    id: id,
    showDetail: false
    });
    }
    };
    ```

    > Defer is also able to somewhat `catch` the thrown promises, and only apply the
    > state changes after all of the child async operations are completed.
    @@ -234,41 +315,70 @@ can be found here<br>

    Here is what Dan had to say about this whole set state defer:

    *****
    ![https://twitter.com/dan_abramov/status/970363904319741952](https://imgur.com/UTVzgth)

    ---

    ### \*\*Code Splitting with

    ### **Code Splitting with
    **[React.lazy](https://reactjs.org/docs/code-splitting.html)** and
    React.Suspense**
    React.Suspense\*\*

    <br>
    <br>

    > The React.lazy function lets you render a dynamic import as a regular component.
    Before:

    ```
    import React from 'react';
    import RestaurantListComponent from './RestaurantList';
    function App() {
    return (
    <div>
    <RestaurantListComponent />
    </div>
    );
    }
    ```

    **Note**: In the above implementation the **RestaurantListComponent** will be
    part of your main bundle and will not be lazy-loaded.

    After:

    ```
    import React, { Suspense, lazy } from 'react';
    const RestaurantListComponent = lazy(() => import('./RestaurantList'));// code-splitted, on demand loaded component
    function App() {
    return (
    <Suspense fallback="Loading...">
    <RestaurantListComponent />
    </Suspense>
    );
    }
    ```

    **Note**: With this approach, **RestaurantListComponent **will be a code
    splitted component loaded on demand.

    ![](https://cdn-images-1.medium.com/max/1600/1*eUDG6xBLoo7Vcmvq-hyUQw.gif)
    <span class="figcaption_hack">Example of lazily loaded component in a chunk “**1.chunk.js”**</span>

    *****
    ---

    **How to use these API’s?**

    * React.Suspense with React.lazy is a stable API and can be installed from npm as
    the latest stable version of react and react-dom
    - React.Suspense with React.lazy is a stable API and can be installed from npm as
    the latest stable version of react and react-dom

    npm install react react-dom
    npm install react react-dom

    * react-cache and scheduler are unstable. Here is how you can still use them:
    - react-cache and scheduler are unstable. Here is how you can still use them:

    *****
    ---

    ### **Conclusion**

    @@ -281,15 +391,15 @@ Here is the roadmap from the React team for the upcoming releases:<br>

    ### **Resources**

    * [React lazy, Suspense and Concurrent React Breakdown with
    Examples](https://medium.com/@rossbulat/react-lazy-suspense-and-concorrent-react-breakdown-with-examples-2758de98cb1c)
    * [Beyond React 16: Time Slicing and Suspense
    API](https://auth0.com/blog/time-slice-suspense-react16/)
    * [Dan’s JSCONF talk ](https://www.youtube.com/watch?v=nLF0n9SACd4)
    * [React Suspense: Async Rendering in
    React](https://blog.logrocket.com/async-rendering-in-react-with-suspense-5d0eaac886c8)
    * [What’s new in React — Presentation](http://react-suspense-lazy.surge.sh/#/)
    * [Fresh Concurrent React
    ](https://github.com/sw-yx/fresh-concurrent-react/blob/master/Intro.md)
    * [Twitter thread around this
    topic](https://twitter.com/dan_abramov/status/970758867779977217)
    - [React lazy, Suspense and Concurrent React Breakdown with
    Examples](https://medium.com/@rossbulat/react-lazy-suspense-and-concorrent-react-breakdown-with-examples-2758de98cb1c)
    - [Beyond React 16: Time Slicing and Suspense
    API](https://auth0.com/blog/time-slice-suspense-react16/)
    - [Dan’s JSCONF talk ](https://www.youtube.com/watch?v=nLF0n9SACd4)
    - [React Suspense: Async Rendering in
    React](https://blog.logrocket.com/async-rendering-in-react-with-suspense-5d0eaac886c8)
    - [What’s new in React — Presentation](http://react-suspense-lazy.surge.sh/#/)
    - [Fresh Concurrent React
    ](https://github.com/sw-yx/fresh-concurrent-react/blob/master/Intro.md)
    - [Twitter thread around this
    topic](https://twitter.com/dan_abramov/status/970758867779977217)
  13. vivek12345 created this gist Jan 20, 2019.
    295 changes: 295 additions & 0 deletions Magic of React Suspense with concurrent react and React.lazy API.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,295 @@
    ### Magic of React Suspense with concurrent react and React.lazy API

    ![](https://cdn-images-1.medium.com/max/1600/1*LjRa4DHzTkRCIjGmz1tgjQ.jpeg)
    <span class="figcaption_hack">Magical land of React Suspense, Concurrent React and React.lazy API</span>

    [Dan Abramov](https://twitter.com/dan_abramov) in his talk “[Beyond React
    16](https://www.youtube.com/watch?v=nLF0n9SACd4)” at JSConf Iceland 2018 said:

    > *We’ve built a generic way to ensure that high-priority updates like user input
    > don’t get blocked by rendering low-priority updates.*
    Let’s understand what this means and also get introduced to some of the new
    features coming to React, some of which have been released as part of the latest
    stable release and some of them are still in **unstable** mode and it’s quite
    possible that the implementation of the api might change over time.

    Things we got introduced to in the talk:

    * [Suspense](https://reactjs.org/docs/code-splitting.html)
    * [react-cache](https://www.npmjs.com/package/react-cache)
    * Defer set state with [scheduler](https://www.npmjs.com/package/scheduler)
    * Concurrent React Mode
    * Code splitting with [React.lazy](https://reactjs.org/docs/code-splitting.html)

    *****

    ### **Suspense**

    > React.Suspense in simple words means we can suspend the rendering of our
    > component or components until some condition is met( for example data from an
    endpoint or a resource is loaded) and until then show a fallback(for-example a
    spinner)

    **Why do we need this?**

    If suspense is all about just showing a spinner till data loads, can we not do
    that today as well?

    I mean we have been doing the same thing since a long time by keeping a loading
    state as true and till the data is not fetched we show a spinner and when data
    fetch is complete we set the loading state to false.

    An example of how we have been currently doing it:

    state = {
    loading: true,
    data: null
    }

    So the question is if it can be done even today then what is it that suspense is
    bringing into our codebase?

    The answer to that is yes it’s still possible to use loading state and play
    around with it to show/hide the spinner but as the application grows complex
    this becomes tedious to manage.

    For example:-

    <RestaurantDetail>
    <RestaurantInfo />
    <RestaurantAlbums />
    <RestaurantReviews>
    <RestaurantReviewDetail>
    <RestaurantReviewDetail>
    <RestaurantReviewDetail>
    {...}
    </RestaurantReviews>
    </RestaurantDetail>

    In the above example we can have 4 api calls:<br> 1) **<RestaurantInfo />**
    component making one api call for getting basic information about a Restaurant

    2) **<RestaurantAlbums />** api to fetch all the images of that Restaurant<br>
    3) **<RestaurantReviews />** api to fetch all reviews<br> 4)
    **<RestaurantReviewDetail />** api to fetch some details around those individual
    reviews like comments, likes etc.

    The problem with the above code structure is that we need to somehow manage the
    loading state and data fetching states for all those api calls that are
    happening above.

    **So what is the solution?**

    For the above problem we have multiple solutions which can be as follows:

    * Delegate all api calling logic into the parent container and let all of them
    wait until all data fetching is complete and pass data to child components as
    props. The problem with this approach is now the parent needs to be aware of all
    api calls which are needed by child components and also maintain a complex state
    for all these api responses.
    * Make all the child components smart/stateful components and let each of them
    manage their own **loading** and **data** states. This is complex since
    converting a stateless component to a stateful component is not something we
    would want to do.
    * The third solution is using **Suspense**

    **With Suspense it works differently. How?**

    > With suspense and react-cache, we can use our same functional component and
    > still fetch data from it.
    The difference here being instead of fetching data from a lifecycle method like
    `componentDidMount` we will fetch this data from inside of `render` .

    **How is this even possible?**

    > This becomes possible using `react-cache` and `suspense`
    Now a word of caution, `react-cache` is still unstable and it’s implementation
    or api might change over time.

    An example of how to use react-cache to create a restaurant list fetching
    resource:-

    *****

    ### **react-cache**

    In the above code snippet we are using **unstable_createResource** and as the
    name suggests this is still `unstable`

    > unstable_createResource takes a **function** as one of its arguments and a
    > **hash** **function** as the second argument which is used to create the key for
    the hash map which caches the data.

    The whole suspense and suspended rendering magic comes into play with this
    **unstable_createResource** because this function** throws a promise.**

    <span class="figcaption_hack">Dan’s tweet about cache throwing a promise and react catching it</span>

    A layman implementation of what it might look like could be:

    If you notice, it returns an object with a `read` function which takes `key` as
    a param which is usually the hash key of the hash map and if the data is not
    fetched yet then this read function will **throw a promise** as we see on line
    no 6.

    The actual implementation of this function can be found here:-

    [https://github.com/facebook/react/blob/master/packages/react-cache/src/ReactCache.js#L142](https://github.com/facebook/react/blob/master/packages/react-cache/src/ReactCache.js#L142)

    *****

    **Who will catch this promise?**

    **Error Boundaries **will catch this promise like how they used to catch the
    error thrown by React render.<br> More information on Error Boundaries can be
    found on reactjs.org:<br>
    [https://reactjs.org/docs/error-boundaries.html](https://reactjs.org/docs/error-boundaries.html)

    So now with **unstable_createResource** our **RestaurantList** component would
    look something like this:

    *****

    **Who will implement componentDidCatch?**

    This is where **Suspense** from react comes into play. **React.Suspense** has a
    **componentDidCatch** sort of mechanism which will catch this promise and show a
    fallback until the promise is resolved.

    This concludes the topic of using React.Suspense to suspend rendering until data
    fetching is complete and until then show a fallback. We learnt about
    **react-cache** in this topic and how it can be used to throw a promise and
    suspend rendering.

    *****

    ### **Concurrent React**

    To take advantage of the asynchronous capabilities of concurrent React, We
    change the way we render our root `<App />` element.

    Where we do this in standard React:

    ReactDOM.render(<App />, document.getElementById('root'));

    We do this for concurrent React:

    ReactDOM.createRoot(document.getElementById('root')).render(<App />);

    That is all that needs to be changed to enable Concurrent React.

    This brings us with a new magical capability which is:-

    * `maxDuration` prop- this is the time in **ms** after which our fallback
    component will show up. This will avoid screen flickering issue which usually
    occurs on faster network where the loader shows up for few ms and then the data
    comes immediately. This will make sure that for faster networks Spinner will
    never show up thereby avoiding screen flickering.

    *****

    #### React.StrictMode

    If you are developing in React 16.6, what has been recommended is to wrap
    `<React.StrictMode>` around `<App />` so any unsupported features you may
    integrate will be prompted as warnings in your development console.

    Wrap strict mode around your app like so:

    ReactDOM.render(
    <App />
    , document.getElementById('root'));

    *****

    ### **Defer Mode in Concurrent React**

    > We can defer certain setState calls and let it wait until some other important
    > operations like data fetching finishes for example clicking on a restaurant card
    and not rendering the detail page until all the data for the detail page has
    been loaded.

    This is the kind of stuff it allows you to do:

    *****

    To use this we need another **unstable** api which is part of an **npm** package
    called as `scheduler`

    import { unstable_scheduleCallback as defer } from "
    ";

    To defer a setState call we can do like the function below where I am delaying
    showing the detail page until the data for that page is loaded.

    > Defer is also able to somewhat `catch` the thrown promises, and only apply the
    > state changes after all of the child async operations are completed.
    Complete example with concurrent react, createResource, Suspense and defer mode
    can be found here<br>
    [https://codesandbox.io/s/kwjjovx5wo](https://codesandbox.io/s/kwjjovx5wo)

    Here is what Dan had to say about this whole set state defer:

    *****

    ### **Code Splitting with
    **[React.lazy](https://reactjs.org/docs/code-splitting.html)** and
    React.Suspense**

    <br>

    > The React.lazy function lets you render a dynamic import as a regular component.
    Before:

    **Note**: In the above implementation the **RestaurantListComponent** will be
    part of your main bundle and will not be lazy-loaded.

    After:

    **Note**: With this approach, **RestaurantListComponent **will be a code
    splitted component loaded on demand.

    ![](https://cdn-images-1.medium.com/max/1600/1*eUDG6xBLoo7Vcmvq-hyUQw.gif)
    <span class="figcaption_hack">Example of lazily loaded component in a chunk “**1.chunk.js”**</span>

    *****

    **How to use these API’s?**

    * React.Suspense with React.lazy is a stable API and can be installed from npm as
    the latest stable version of react and react-dom

    npm install react react-dom

    * react-cache and scheduler are unstable. Here is how you can still use them:

    *****

    ### **Conclusion**

    To conclude, I am really excited about all these api’s to be stable soon.<br>
    What are your thoughts on these features? Let me know in the comments section!
    😊

    Here is the roadmap from the React team for the upcoming releases:<br>
    [https://reactjs.org/blog/2018/11/27/react-16-roadmap.html](https://reactjs.org/blog/2018/11/27/react-16-roadmap.html)

    ### **Resources**

    * [React lazy, Suspense and Concurrent React Breakdown with
    Examples](https://medium.com/@rossbulat/react-lazy-suspense-and-concorrent-react-breakdown-with-examples-2758de98cb1c)
    * [Beyond React 16: Time Slicing and Suspense
    API](https://auth0.com/blog/time-slice-suspense-react16/)
    * [Dan’s JSCONF talk ](https://www.youtube.com/watch?v=nLF0n9SACd4)
    * [React Suspense: Async Rendering in
    React](https://blog.logrocket.com/async-rendering-in-react-with-suspense-5d0eaac886c8)
    * [What’s new in React — Presentation](http://react-suspense-lazy.surge.sh/#/)
    * [Fresh Concurrent React
    ](https://github.com/sw-yx/fresh-concurrent-react/blob/master/Intro.md)
    * [Twitter thread around this
    topic](https://twitter.com/dan_abramov/status/970758867779977217)