
React v16.6.0: lazy, memo and contextType - sophiebits
https://reactjs.org/blog/2018/10/23/react-v-16-6.html
======
andrewstuart
I'm a huge ReactJS fan, but right now I'm doing some development with Django
and plain old HTML/JavaScript template forms and I'm finding it incredibly
easy and my general pain level seems to be lower. I haven't figured out why
exactly.

Probably I'm just not doing anything very sophisticated. It's just a plain old
form driven website - that would account for it.

~~~
silviogutierrez
Agreed. But as soon as you hit _any_ dynamic behavior, you kind of end up
wishing you could "drop" into React.

That's why I built the following project:
[https://github.com/silviogutierrez/reactivated](https://github.com/silviogutierrez/reactivated)

It's very early on, but essentially, completely replaces the template
rendering with React components. Still regular markup, but whenever you need
dynamic behaviors, it's trivial. And it's all server side rendered.

So basically, looking at
[https://github.com/silviogutierrez/reactivated/blob/master/c...](https://github.com/silviogutierrez/reactivated/blob/master/client/templates/TrinketList.tsx)

You can see the traditional Django context becomes "Props" in the top level
component. Then it's React all the way down.

Notes:

1\. The most complicated part is the initial setup. You do need to run NodeJS,
webpack + Django server. Working on improving that.

2\. I like TypeScript and use it here. But theoretically it'll be optional.
The Django+Python part is also statically typed using MyPy.

3\. No instructions whatsoever yet. But you can see a live site using this
stack here:
[https://www.silviogutierrez.com/](https://www.silviogutierrez.com/) . Notice
it's server rendered but has dynamic behaviors that are _trivial_ in React but
harder with jQuery + Django. Example:
[https://www.silviogutierrez.com/blog/making-cck-fields-
read-...](https://www.silviogutierrez.com/blog/making-cck-fields-read-only-
drupal-6/) Look at the nested commenting and moving the form around. Very easy
in React.

4\. Because of the architecture, adding a much-better-turbolinks style Ajax is
trivial. Click around the site above (loading indicator not yet added). The
page is re-rendered entirely on the client but gets a server AJAX response.

Hope that's interesting info. If you'd like to try it out, definitely let me
know. Once you overcome the setup hurdles, it's amazingly productive. As in,
if all you wish to do is `{{ form }}` like old school Django, here's the
equivalent sample template:
[https://github.com/silviogutierrez/reactivated/blob/master/c...](https://github.com/silviogutierrez/reactivated/blob/master/client/templates/FormView.tsx)

~~~
devxpy
I have a similar project, that doesn't require you to setup webpack, and
integrated beautifully with django

[https://github.com/pycampers/react-pages](https://github.com/pycampers/react-
pages)

~~~
silviogutierrez
Neat! In this case, it took a _lot_ of work to get the forms "fielded" in
React world. So you can individually render fields, etc. But yea, setup is
currently a pain.

~~~
devxpy
I have a quite very crude implementation of form fields on my side, which
annotates the type of formfield (as a string) along with several other useful
things, like id_for_formfield, html_name etc.

\--

In your
[https://github.com/silviogutierrez/reactivated/blob/master/c...](https://github.com/silviogutierrez/reactivated/blob/master/client/templates/FormView.tsx)

    
    
        import {Form} from '../components/Form';
    

I can't find `../components/Form`. Where is the source for that?

\---

Here are the fields I was able to extract, meaningfully.

[https://github.com/pycampers/react-
pages/blob/417ec24129b80b...](https://github.com/pycampers/react-
pages/blob/417ec24129b80b91c4f429f19a0334974a2c286f/react_pages/views.py#L59)

It still doesn't seem enough for building anything serious though.

------
ianschmitz
With the addition of `React.memo`, is it still the recommendation from the
React team that we only use `React.PureComponent` and `React.memo` in places
where we profile and identify performance bottlenecks?

I seem to remember reading that adding something like `PureComponent` or
implementing `shouldComponentUpdate()` can actually slow things down due to
the cost of props/state comparison?

Either way thanks for another great release team! Suspense has me super
excited!

~~~
danabramov
Yeah, nothing changed there. If you run checks that are always false then it's
wasted time on checking.

Brian recently wrote a profiler to help you find where plugging memo is
useful:

[https://reactjs.org/blog/2018/09/10/introducing-the-react-
pr...](https://reactjs.org/blog/2018/09/10/introducing-the-react-
profiler.html)

~~~
dbbk
Every time I see stuff like this it just makes me think, why does the
developer have to care about this? For example take Glimmer, you never have to
do `shouldComponentUpdate` or anything like that, it's just maximally
performant out of the box.

------
breeny592
Great work from the React team on this release - it's exciting to see some big
enabling features like suspense and lazy being baked into the library (rather
than falling back on solutions like react-loadable).

------
hoppelhase
Do lazy + Suspense replace the react-loadable [1] package?

[1]: [https://github.com/jamiebuilds/react-
loadable](https://github.com/jamiebuilds/react-loadable)

~~~
ianschmitz
One nice feature of react-loadable is that you can specify a threshold (300 ms
by default I think) which is used to prevent rendering of the loader until
after the threshold is passed so you don't get a flash of the loader. Users
can perceive it as being slower if you have a quick flash of a loader then
show the component.

I haven't seen anything yet about the Suspense component supporting this. I
imagine you could wrap the suspense component with your own to achieve this
behavior, but it's nice not to have to reimplement.

~~~
hoppelhase
Is this planned for the Suspense API?

~~~
danabramov
>One nice feature of react-loadable is that you can specify a threshold (300
ms by default I think) which is used to prevent rendering of the loader until
after the threshold is passed so you don't get a flash of the loader. Users
can perceive it as being slower if you have a quick flash of a loader then
show the component.

There is more nuance to it — essentially, React Loadable renders a _hole_
instead of the spinner in this case. Which isn't much better than a spinner
because you still see the intermediate state.

With the current release of Suspense, you can do it if your fallback component
renders spinner after a timer. So that's not difficult. But we also don't
think it's good either.

Instead, when we release Concurrent Mode, you can _avoid showing the change
altogether_ until a certain threshold passes. That's the `maxDuration` prop
(which doesn't do anything outside of Concurrent Mode).

So you don't even show a hole. Instead, the whole UI is "suspended". And then
the fallback kicks in if takes too long.

This might be a bit hard to imagine since no mainstream UI library can do this
yet. So you might want to check the second half of my talk (on Suspense) to
get a sense for what it's like: [https://reactjs.org/blog/2018/03/01/sneak-
peek-beyond-react-...](https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-
react-16.html)

That's our end game.

------
mbrowne
I am wondering how to avoid unnecessary re-renders using `contextType`. With
the render props pattern, you could write a component e.g. <Subscribe> that
subscribes to a store and accepts a prop to indicate the specific data
dependencies of your component (similar to mapStateToProps() in redux -- here
it could be called mapContextToProps()). It's nice to be able to use `static
contextType` but it would re-render anytime any property of your context
object changes (just as would be the case when using a Consumer directly).
That might be fine for something like a theme but wouldn't scale to a more
general state management solution.

~~~
mbrowne
Thinking about it some more, for function components I suppose this might be a
good use case for a hook...

------
mcintyre1994
I was definitely mis-understanding functional components because I'd have
assumed that memo was the default behaviour. Could anybody with more
experience/knowledge suggest what sort of functional components you'd want to
re-render if their props don't change? Cool that there's an easy way to get
that behaviour now though! :)

~~~
sophiebits
By default, React doesn’t check if individual props are equal. This is for two
reasons:

1\. We support using mutable objects in props. Even if a prop is reference
identical to the last render, the component might be reading some property of
it that has changed.

2\. Checking equality of props takes time. In the (common) case where a parent
rerenders and it’s children need to change in response, any time we spend
comparing will be extra overhead on top of the actual render cost. Often
rerendering is fast anyway and adding more comparisons only makes it slower.

Because of these, we don’t do these checks by default. Instead, we recommend
adding memo/PureComponent/shouldComponentUpdate in places where you know it
will make a difference.

~~~
mcintyre1994
Thanks for this explanation, that makes a lot of sense! :)

------
Waterluvian
Pretty excited by these features. Great work!

I still need to go find my "aha!" moment for contexts. I get them but I
haven't developed that intimacy where I know when I should use them.

Also I'm finding it trickier to know which method for component definition to
reach for. I love that we have freedom of choice. But I struggle to pick
between classes (pure and not), class methods (perhaps to clean up big
render() methods or define class-relevant subcomponents), and functional
components (memoized or not). I had someone getting into React asking me about
it and I didn't have a really solid answer. I think I just confused them. This
is probably just a tutorial/documentation/examples kind of problem.

~~~
frio
We use it for application-wide stuff that would need to be drilled down
several layers, and _isn 't_ state. So -- as a contrived example -- if we have
a form that submits to a configurable URL (configurable at build time), then
we wrap that URL up in a context. The eventual FormComponent will then consume
the URL from context, rather than being drilled through n-layers of React
components as a prop. Redux isn't the right answer here, because that URL's
never going to change, but it used to do the job in a pinch.

Other examples are react-redux itself (which uses the legacy context API) or
react-intl (which uses the legacy context API), or a themeable widget set. You
put a wrapping context at the top of your tree like <Provider>, <IntlProvider
messages={someMessages} locale={this.state.locale}> or <ThemeProvider
theme={myEmployersColours}>, and then nested deeply in the application you use
a <Message> that will look at the context provided by the IntlProvider, or the
context provided by the theme, to pull out the actual message/colors it should
show.

Basically, context is useful for encapsulating cross-cutting concerns :).

~~~
Waterluvian
Aha. Okay I think I'm having a moment. I could possibly use this to pass a
reference to a websocket stream for streaming data that's way too high
frequency to be handled with redux actions.

Say, 100 robots driving around, displayed by a map component. I want to handle
the addition of removal of a robot as an action but the actual 10hz pose
updates can just be handled by the canvas and ignored by react entirely.

Maybe even context for camera streams too.

Previously I would just handle a websocket stream as a global. Yuck.

~~~
acemarke
Note that context updates do require that React walk over the component tree
to find the appropriate consumers, and that itself has a cost. In fact, at the
moment, it seems to be _relatively_ expensive, per the discussion in this
issue :
[https://github.com/facebook/react/issues/13739](https://github.com/facebook/react/issues/13739)
.

We're actually working on converting React-Redux to use `createContext` in
version 6. I had hoped that it would be a big performance improvement, but
unfortunately our (admittedly limited) perf benchmarks indicate that the
experimental v6 branches are slower than our current v5 release build. In v5,
the individual connected components subscribe to the Redux store, and can bail
out of calling `setState()` if no update is necessary. In v6, we've only got
one subscription (in `<Provider>`), but any Redux store update requires that
React walk the tree and update the context consumers so they can run
`mapState`. So, React _always_ gets involved, whereas before we might skip
React if nothing had changed.

Per that issue, I'm hopeful that the React team can optimize deep context
updates in the near future.

------
thesunny
contextType is a much needed shortcut but I wish instead of this:

    
    
      static contextType = SomeContext
    

they did something like:

    
    
      static contextMap = {
        form: FormContext,
        app: AppContext,
      }
    

as it seems limiting to only allow one context.

In the example above, the context values would be available in this.form and
this.app

~~~
danabramov
This has been suggested in the RFC discussion
([https://github.com/reactjs/rfcs/pull/65](https://github.com/reactjs/rfcs/pull/65)).

We intentionally didn't do it for several reasons:

* It adds extra object allocations on every render which adds up when your project grows

* It's harder to express in a type system (e.g. Flow or TypeScript)

You can use the low-level Consumer API to read multiple contexts but in this
particular shortcut we're not going to support it.

~~~
pcmaffey
The other angle to solving this problem would be adding lifecycle methods to
React.Context (instead of using render props), which could eliminate the need
for multiple contexts. Making Consumer contexts more efficient & composable.

~~~
danabramov
We've thought about a spectrum of solutions and plan to present more proposals
soon.

------
throwaway3265
Is React.memo comparing deeply/recursive or at least deterministic
JSON.stringify comparison? Or still going for shallow comparison?

~~~
sophiebits
Still shallow.

We usually recommend avoiding deep checks because

(a) the concept of deep equality is pretty nebulous and hard to design in a
predictable, precise way, and

(b) deep equality checking can be slow, often just as slow (or slower) than
the actual rerender – in which case the memoization is only hurting you.

(If you want to do deep equality anyway, you can pass a second argument to
React.memo to specify a custom comparator.)

~~~
throwaway3265
I agree about those statements, just curious since that was probably the most
important concept I had to learn about "advanced" React.

------
platz
is it just me or does contextType/context abandon the FP parts of React?

~~~
danabramov
Not quite sure what you mean. Maybe the RFC might explain the motivation a bit
more?

[https://github.com/reactjs/rfcs/blob/master/text/0065-contex...](https://github.com/reactjs/rfcs/blob/master/text/0065-contexttype.md)

The contextType API serves as a convenience for the most common case of
accessing context today. While the existing render prop API is more versatile,
the fact is it's awkward in some cases with classes (e.g. when you need to
access it in lifecycle).

And unfortunately that means that people are stuck using the legacy context
API which is even worse (it makes React bigger and slower). So we're adding a
convenience to help people migrate to the new implementation with a slightly
more familiar syntax.

I guess in a way it _is_ a compromise, but in our view it's better than if
people just kept using the legacy context API.

Hope that makes sense.

~~~
nicoburns
contextType API looks great. I thought when I saw the new context API that it
looked neat from a code cleanliness point of view, but a bit of a pain to use.
This looks much easier :)

------
jliptoo
Does anyone know if the next version will be 17.0 or can we expect more 16.x
version even by mid 2019? Need this info for work.

~~~
danabramov
We expect to release more minor version(s) prior to 17.

~~~
jliptoo
Thanks. Do you know if react 17 will be out by mid-2019? Need this info for
work. Specially support for SSR. Thanks.

~~~
danabramov
What do you mean by "support for SSR"? Can you elaborate?

All our releases support SSR. But some specific features need to wait for a
new async server renderer. I can't tell you when that's going to happen
although it's most likely within 2019.

~~~
jliptoo
I'm talking about react Suspense for SSR. The blog post says "Note: This
feature is not yet available for server-side rendering. Suspense support will
be added in a later release.".

Is there an RFC somewhere about that new async server renderer?

~~~
danabramov
Not yet. I expect that it will be done in 2019 but can't give you anything
more specific at the moment.

