
React v17.0 Release Candidate: No New Features - jack_hanford
https://reactjs.org/blog/2020/08/10/react-v17-rc.html
======
simonw
"It has been two and a half years since the previous major release of React,
which is a long time even by our standards!"

As a mostly Python and only occasional JavaScript developer, it always felt
like the biggest challenge in the JavaScript community was how fast everything
moved - new libraries, frameworks and ideas would tumble past at the rate of
one every few weeks, and it felt impossible to keep up.

I've been feeling that a lot less recently, and maybe the fact that React has
been steady for 2.5 years is part of the reason.

~~~
dawnerd
I second you on that. The number of times I've had to rewrite code because a
framework decided to break everything with little warning.. I don't even want
to think about it actually. I get wanting to make code better but gesh people,
do some planning and figure out a direction to move a project.

Also it seems JS devs don't understand semver either. Massive breaking changes
in patch or minor versions are just evil.

~~~
onion2k
I've had similar experiences with JS libraries, but not so much with React.
The React team are much better at managing to keep things backwardly
compatible than most.

~~~
jakelazaroff
I really like the React approach to upgrades: if your app works with version N
with no warnings, it will work with version N+1.
[https://reactjs.org/docs/faq-versioning.html](https://reactjs.org/docs/faq-
versioning.html)

------
jitl
I'm excited to see the work on the Modern Event System land. I tried to dig
into all the events code in React to understand how events in React Portals
bubbled up because I wanted to prevent them from bubbling out of the portal in
many cases (GH issue:
[https://github.com/facebook/react/issues/11387](https://github.com/facebook/react/issues/11387)).
In 16.x, the modern event system was in the tree but unused by default, and it
was very confusing to try to trace event handling logic between the two event
systems. Removing the legacy event system will make the event system much more
accessible to new contributors.

Can someone on the React team speak to how event delegation works when there
are portals present? Where is the event handler for a portal bound, and how
does the new events system handle event bubbling across multiple versions of
React in portal trees?

~~~
danabramov
Yeah, we've removed a lot of code and also a lot of abstraction so the event
system should be easier to follow now. We listen to events on both roots and
portal containers — this is why it keeps working.

I can't speak to the exact semantics of how portals work with nested trees,
but if you find an issue, please file one on our tracker. Some are expected to
be impossible to solve, but hopefully we handle the common cases well.

(I would ask Dominic who worked on this but he just went on a much needed
holiday break.)

------
Karupan
I've become increasingly disillusioned with the JS ecosystem over the past
couple of years, but React still delivers. I can still chuck it in a script
tag and start writing components if needed (without JSX). I haven't really
used hooks yet and don't plan to, but as long as "legacy" class based
components are supported, I will use them.

Thanks for maintaining backward compatibility, which is not very common in the
JS world. And congrats on the release!

~~~
oaxacaoaxaca
Just chiming in to say that I too hope class components will continue to be
supported. I worry that they'll announce otherwise in a couple years.

Class components are so stupidly simple to read and write. I appreciate the
work put into function components, but to me they make things unnecessarily
complex. Just the fact that they took callbacks and other functions from
methods – where things are separate, clean, standard – to nested functions –
where things are not separate (some local variables, some closure variables),
not clean (no possible way to unit test a nested function in isolation), and
not standard (object methods are a language feature, use them!) – seems like a
huge step backward.

~~~
nightski
You can create isolated functions instead of nested functions wherever you
want. Just pass in params instead of using closures. This is entirely up to
the developer.

~~~
untog
_You_ can, yes. But the developer working on the codebase you’re going to
inherit might not. Class components are usefully opinionated in that way.

~~~
oaxacaoaxaca
Yep. And isolated functions are a solution, but sometimes it just makes way
more sense for that function to be a method of a class. And for the function
component to be a class component. I think there's space for both types of
components, and I just hope that class components don't become deprecated.

~~~
nightski
Absolutely there are cases where class components make sense. I highly doubt
they would ever depreciate them.

------
rafaelturk
I wish this approach to be followed by all major repos and maintainers and
become a new trend across all the tech industry.

By creating `bridge` release, the React community created a safe, well know
and stable release that works as bridge for the upcoming complex, feature
rich, release.

So: Complex Release -> Stable `bridge` Release -> New Complex Release.

Anyone can stay as long as they want in the bridge release, others can quickly
move forward to the next release cycle.

------
afidrya
It contains a very serious breaking change: cleanup in useEffect is now being
executed asynchronously. I might not be seeing something, but I think this
means all patterns like the one below will now have hard to catch racing
conditions.

    
    
      const [x, setX] = useState()
      useEffect(() => {
        let isMounted = true
        someAsyncFunc(result => {
          if (isMounted) {
            setX(result) // should not be called on dismounted component
          }
        })
        return () => { isMounted = false }
      }, [])
      return <MyComponent x={x} />
    

In this example it's possible that component will be unmounted, then
completion handler will run and try to modify state before cleanup function
will be able to set the flag.

Imo choosing a different name for new useEffect would be better (like
useAsyncEffect or introducing a parameter), because just changing its behavior
won't even result in compilation errors or guaranteed run-time errors, only
make old code unstable.

Is there a way to reliably detect if component is still mounted before
updating it when doing async operations in effects?

~~~
danabramov
Thanks for raising this concern. This particular example is not a problem in
practice because React will not fire the warning about setting state in the
short period between unmounting and cleanup. (We have special code and tests
specifically for this case.)

So code like this can stay written exactly as it does today. As noted in the
blog post we’ve only had to modify ~20 components out of thousands so although
this change _may_ cause some breakage (please report anything unusual to the
issue tracker!) we’re fairly confident that such common patterns continue to
work.

(Edit: added this to the post.)

------
emptysea
I’m excited for no event pooling. I’ve been bitten by that a few times when
refactoring.

Thought about making a lint for it but never got around to it.

[https://reactjs.org/blog/2020/08/10/react-v17-rc.html#no-
eve...](https://reactjs.org/blog/2020/08/10/react-v17-rc.html#no-event-
pooling)

------
jameslk
It's refreshing to see a major release of a frontend library that doesn't
completely redo the API (React Router and Angular, take note). I remember
there was a time when a bunch of features were being considered to be bolted
on to JSX which was going to be called JSX 2.0[0]. I'm glad that never
happened. Maybe the next version of React can even remove features, like
hooks.

0\.
[https://github.com/facebook/jsx/issues/65](https://github.com/facebook/jsx/issues/65)

~~~
acemarke
I'd still _loooove_ to have "prop punning", ie, shorthand passing of props
based on local variable names equivalent to ES6 object literal shorthand:

    
    
        <MyList items selectedItem onItemClicked />
    

Doesn't seem too likely to happen at this point, though.

~~~
Gaelan
That conflicts with HTML syntax, no? <input disabled /> is equivalent to
<input disabled={true} />.

~~~
acemarke
Which is why the current JSX syntax uses that as a synonym for
`disabled={true}`. Agreed that it matches HTML better, but having written an
awful lot of `someLongVariableName={someLongVariableName}`, I sure wish I
could stop repeating myself there.

~~~
floydnoel
I, too, find it ridiculous to repeat `foo={foo}` over and over again. So I use
the spread operator with ES6 shorthand object syntax. Now it’s `{...{ foo }}`.
No breaking changes needed!

------
jamesknelson
Was just thinking that we're probably due for a major release sometime now
that Concurrent Mode seems to be starting to mature a little (disclaimer: it's
still experimental, don't use it in production yet, etc.)

I'm sure the React team must be eager to get all the juicy changes out of the
experimental branch and into the hands of developers. So it's great to see
though that they're still taking their time to do it properly. Looking forward
to seeing what come nexts :)

------
untog
Hm. I like the idea of gradual upgrades in theory, but I worry the reality
will be sites loading at least two versions of React semi-permanently. And
possibly even worse, you end up with an NPM dependency nightmare of off-the-
shelf component X using an entirely separate React runtime.

Yet more excess JS downloading and running on client devices, all in the name
of superior developer experience. I hope my cynicism is proven wrong!

~~~
danabramov
Totally hear your concern! To be clear though, it's not like we're forcing
anyone to follow this approach. It was just broken before, in the same way
that putting React inside a Vue/Svelte/jQuery app was subtly broken. So we've
fixed the root cause but I totally agree it's only a solution to be used as a
last resort. (E.g. like in our case, where many "long tail feature" components
were written in 2013 and no teams own them.) In either case, even if you
follow this approach, we strongly recommend to only load the second version
lazily on screens that need it — like the demo shows.

It's very suboptimal but I think it's still better to have that option than
not to have it — or to try it and run into insurmountable problems. Especially
in big long-running projects like internal company dashboards where long-term
maintenance is more important than time to first render.

(I don't know why you're being downvoted though! I think your concern makes a
lot of sense, and we're also sensitive about how to balance the messaging so
that people don't use this unnecessarily.)

------
f223ff23f
Jet, Angular 9 has such slow build times I can even imagine anyone would use
it:

[https://github.com/angular/angular/issues/37293](https://github.com/angular/angular/issues/37293)

I have 2 comparable applications (in size) and React build times are 10 times
faster than Angular.

~~~
throwaway329482
It's sometimes easier and saner to develop a new component on something like
stactblitz or a new angular project than make a change, wait 20s+ for
compiler+browser to compiler and load code and view the new change. And
repeat. And losing the hot-reloading with state b/c of the OOP heavy
architecture in some shops, well that's not helping speed up write/reload/view
change cycle at all.

And as you write larger and larger apps, with hundreds of components, it's
just ridiculous how poorly the first-party tools handle that kind of code
scale. Your only choice it to buy into Bazel to maintain some sense of sanity
and productivity albeit some of which gets diminished with the overhead of
learning, using and maintaining bazel for the project.

Complexity on top of complexity, nothing about Angular is simple.

------
jmnicolas
New version of a JavaScript framework. No new features. Mind blown.

------
wildpeaks
No new feature, yet contains breaking changes.

~~~
danabramov
As stated in the post, the breaking changes are intentionally minimal. For
example, we haven't removed any of the APIs that were originally slated to be
removed in 17.

~~~
danpalmer
I think the marketing line of "No new features" could lure people into a false
sense of security on this upgrade, even if the breaking changes are minimal.

By all means make breaking changes, just maybe tone down the marketing.

~~~
turboturbo
How is a very elaborate blog post indicating the what & why considered
marketing?

In my opinion this goes WAY beyond the usual changelog entry in other
repositories.

~~~
danpalmer
Don't get me wrong, this is great documentation, very high quality, and well
done to the React team for a great release and what I think is a solid
decision around what to include and what not to include in this release.

I think it's important to understand though that React is _marketed_, and
unfortunately for many a name as clearly stated as this will likely define
their expectations significantly. This could be especially pronounced for
those who are less proficient in English.

------
throw03172019
Random thought after reading:

I wish macOS / iOS / iPadOS would have a version without tons of new features.

~~~
danabramov
Remember Snow Leopard? I miss that.

~~~
madeofpalk
The version that you wipe your main user account if you used the guest
account?

~~~
Wowfunhappy
That was bad, but it was fixed very quickly, and Snow Leopard had a long life.

------
taooftea
React hooks is influenced by Dan, the author of Redux, not a fan of them both

~~~
msikora
IMO Hooks is the best thing that happened to React. Once you get used to it it
is a lot more clean and productive. It requires you to unlearn a few things
though, e.g. don't think about component lifecycles, but think about data
flow/changes. Once you get used to it is a lot more productive and enjoyable
way of developing React apps.

~~~
mybestguess
I believe it would have been better to have Hooks as a separate library, not
part of React. For the developer it is just another design pattern, not really
an improvement, especially if you look at all the edge cases and issues you'll
find around.

Personally I don't like the design pattern, a matter of taste. But it's very
annoying now in the market to have mixed React and Hooks codebases, with all
their issues..

