Awesome! Glad this is finally out, and really looking forward to seeing what features the React team adds in follow-up releases.
The Working Group model really helped us in the community give feedback - APIs like `useSyncExternalStore` wouldn't have happened otherwise, and I really appreciate the responsiveness on that topic.
I think it's basically ready to go, but I haven't had a chance to really test out the SSR support I added a couple months ago. I'd love to have some help testing that out.
v7 will _run_ with React 18, but v8 has been specifically reworked to behave correctly when used with React's new "Concurrent Rendering" capabilities. We've also converted React-Redux itself to TS (no more separate types package).
Ideally, I'd like to release v8 as final in the next week or two.
Thank you Mark for your selfless work to push this project forward. RTK Toolkit was an absolute game changer and has been a foundation that our product would suffer immensely without.
Mobx and Redux Toolkit have some relatively similar capabilities. It largely depends on whether you prefer FP-style code and explicit logic (Redux), or OOP-style code and implicit update behavior (Mobx).
Any particular aspects of Mobx you feel are easier to use, or parts of Redux you feel are harder? FWIW if you haven't looked at Redux recently, it's changed dramatically in the last couple years. "Modern Redux" with Redux Toolkit and the React-Redux hooks API is _much_ easier to use than the older-style "hand-written" patterns. With RTK, there's no `const ADD_TODO = "ADD_TODO"`, separate action creators, or object spreads for immutable updates. RTK's `createSlice` auto-generates action creators for you, and includes Immer for "mutating" immutable updates in reducers.
You can see the differences in our rewritten Redux docs tutorials:
Also note that last year we released a new RTK Query data fetching and caching API that's included in Redux Toolkit, which is a full-featured data caching abstraction. Define some API endpoints, get React query and mutation hooks automatically:
To be clear, Mobx is a great library, as are other packages like Zustand, Jotai, XState, and React Query. You should use whatever works best for your own use cases and preferences.
But, it's also true that most people's opinions of Redux are based on the older patterns that have been obsolete since 2019, and we get a ton of highly positive feedback about RTK on a daily basis, with people telling us how much they love to use it.
The fact that you still have the energy to reply to all these "isn't Redux bad/old/dead?" comments is a testament to the patience it must have taken to get this release out. Thanks for all your efforts.
Refactored a web app with traditional Redux logic to use Redux Toolkit and it really does make the logic much more pleasurable to read and maintain. I wasn't in love with the createAsyncThunk + builder.addCase pattern but it worked well enough in practice and isn't very hard to follow.
FWIW we'd _like_ to add the ability to define thunks inside of `createSlice`, but there's TS type circularity issues we've been unable to solve, so that's kept us from making it work right.
Also, I'd be curious to see if RTK Query can handle your data fetching use cases.
Sorry, I should have specified that it’s in work unrelated to RTK. I was just curious if the bugs we encounter are the same ones.
Unfortunately the circularity issues that are closely tracked in the TypeScript repo don’t seem to be making much progress, and in some cases, it seems like TS is fundamentally incapable of working with circular references in some contexts.
Like I was saying though, I find it hard to tell at times if I’m running into real limitations of the type system or I’m short a few IQ points, haha.
It was indeed the need to define the thunks outside of the slice that irked me, but with multiple thunks for a slice, I just wrote them as part of their own module.
I wish React removed all the compatibility code it has with Internet Explorer and the likes and worked on minimising the weight. Also the synthetic events reactivity system seems a bit outdated.
We plan to do this in a close follow up release! Automatic batching was one important step, because it starts to treat native events the same as events that goes through the synthetic event system. The rest will be a bigger breaking change for some folks though, so we didn't want to include it in this release, which is focused on giving users a smooth upgrade to start using concurrent features.
We've announced removal of IE support but we haven't actually removed the related code. We will likely do that in React 19 together with other breaking changes to the React DOM bindings. I wouldn't expect this to dramatically cut the size. Overall, we tend to focus on changes that increase the performance of the application holistically (see https://twitter.com/reactjs/status/1508847169905864707 and next several tweets) rather than focus solely on the bundle size of React itself (which is fixed and becomes a smaller % as the app grows). But we've definitely accumulated some cruft we'd like to drop sooner rather than later.
That’s the size of the folder and its dependencies in node_modules, not the size of what gets sent over the network. You’re looking for Bundlephobia [1].
react itself is also tiny; it only adds 2.5kb to your bundle size [2] (a 300b reduction from v17). react-dom is the much larger dependency, although as of right now Bundlephobia errors out when trying to analyze the newest version [2].
EDIT: they’ve got react-dom@18.0.0 working now and it’s indeed slightly bigger than the previous version: 41.7kb vs 39.4kb.
I remember danabramov claiming more than once on twitter to people praising preact's bundle size, that it also came with a performance cost when it came to diffing and rendering because React had much more code to handle the many edge cases where preact would hit walls.
Shoot. You’re right. Here’s the quote from a preview release:
“In this release, React is dropping support for Internet Explorer, which is going out of support on June 15, 2022. We’re making this change now because new features introduced in React 18 are built using modern browser features such as microtasks which cannot be adequately polyfilled in IE.
If you need to support Internet Explorer we recommend you stay with React 17.”
Not the OP, but we have an IE support requirement that comes from the NHS. They do actually seem to have Chrome available on their machines these days, but they didn't when we signed the contract and lots of their users still use IE11 so we'll be continuing to support it at least until the June deadline.
They'll almost certainly be on LTSC windows which I think means they can continue to use IE11 with security updates beyond the deadline, but we might be able to persuade them to drop the requirement on us at that point.
If it weren't for 3rd party libraries I wouldn't actually mind supporting IE11 too much. It's no IE6. But not being to upgrade libs is a problem!
You’re right that IE 11 isn’t too bad. The other day I was looking around and discovered it supported web sockets. It does have some surprisingly new stuff you think would be missing.
But my main pain point is some relatively simple JavaScript syntax that’s missing. () => {} is a big one. Support for fetch is another.
If it had support for those two things I bet a huge chunk of my shimming and polyfills could be avoided. I can work around other things. But those two just feel too fundamental at this point.
There would be other benefits. Obviously IE 11 is a joke in JS execution speed compared to other browsers, but what would you expect from something that old.
We have one app left that a handful of customers still use in a mode that requires Java applets. Yes, you read that right. We’ve been trying to sunset that feature for a long time but I don’t think a date has been decided yet. If it has it’s probably at least a year in the future.
Some of the fun of the enterprise software world. I’ve wanted to drop it for years. And our JS bundle would shrink a ton without it. One day.
For me: 0.5% of our customers use it, which means as soon as we break IE we get a flood of customer support inquiries. Since we're B2B, the end users using our product often aren't the ones choosing their browser so we can't tell them to just use Chrome.
React is not only introducing layers and layers of abstractions/ concepts that are hard to grasp for a newcomer, they are also reclaiming well-established terms.
> A transition is a new concept in React to distinguish between urgent and non-urgent updates.
> Urgent updates reflect direct interaction, like typing, clicking, pressing, and so on.
> Transition updates transition the UI from one view to another.
“State transition” is a well-established concept, which applies here. We’re also planning to eventually integrate this feature with animations, which would match the other meaning of “transition”. This is why we settled on this term. We get similarly criticized when we come up with our own names for features, so it’s a tricky balance.
I don't get how "layers and layers of abstraction/concepts that are hard to grasp for a newcomer" is your critique here? The literal entirety of tech is layers and layers of abstraction. Also, just because the improvements or new concepts are going to be difficult for newcomers to grasp doesn't mean they are objectively bad. The fact that things are going to be difficult for newcomers should not be an impeding factor on whether or not to build upon existing features. There are ways for newcomers to build up their way to eventually learn the advance concepts. Newcomers are not forced to go from 0-100 on day 1
I’m pretty sure they’re not claiming to have invented transitions. They maybe should have said “a new concept to React” rather than “a new concept in React”.
It's definitely a much simpler react-like library. You don't get the React ecosystem though. If you're looking to step out beyond React, inferno is also worth considering. It focuses on performance rather than bundle size (it's smaller than React, but bigger than Preact).
Well this is an odd thing to say, as there's a whole dedicated compatibility layer. That's not to say it's 100%; relying on specifics of synthetic events, such as bubbling through portals, for example, won't work but it's a drop-in replacement for many users.
I'm also confused by the `useTransition` idea, to be honest I don't exactly know when or where I would use it after reading about it. Sounds like a specific optimization tactic.
Over time, we expect that in most cases you wouldn’t use it directly. Instead, a router might use it for route changes, for example, automatically marking them as transitions. This would make it possible for the user to click a link in the middle of rendering, and immediately handle it instead of being blocked until the render completes.
Fun fact: I started building a couple React apps 5 years ago. Apps still run, but since they're class based component and don't use hooks, the apps feel like ancient. They run perfectly fine though. New guys don't really want to work on in though. Hooray for progress.
Same. Every time a new version gets released I feel a pang of guilt for that poor codebase, but it's been jogging along for 5-6 years with minimal updates and it works like a charm. Fairly big code base as well.
I did upgrade from react-router v1 though... declaring routes as JSON just felt a bit too gross.
Fun fact: very few developers (especially newbies) enjoy working on legacy projects.
New features push the business forward, lets you learn faster, you aren't constrained by the garbage someone else wrote years ago but don't have the budget to change, and it looks better on a resume in an industry where the average term of employment is 2 years because new hires get bigger pay bumps than annual raises give.
Interesting to read about React purposefully doing a double render in dev mode to try and flush out some of the anti patterns, patterns that I know that I am sometimes guilty of. Is the strict-mode docs the best place to read about this kind of thing? the intersection of custom hooks and concurrent mode specifically
Strict Mode docs are probably the best place, yes. If you have a question that isn't answered there, feel free to raise an issue in the React repo and we'll try to help.
Congratulations to the React team on the release! I've kept up somewhat with the development of these features since Dan first introduced some of the ideas at JSConf 3 years ago. It's interesting to see how the APIs have changed over time—I'm sure as a result of some tough lessons learned at Facebook.
As someone who has worked on large React projects worked on by multiple teams, I can see a lot of the value proposition being delivered in this release. I can already think of many places where I'll want to slot in the transition API.
I'm curious if the SuspenseList API is making the cut here or if it's still on the roadmap? I played with it a while back and thought it was very cool, albeit slightly niche perhaps.
The only part that's a bit of a bummer is the recommendation on using suspense for data fetching. I'm already itching to get rid of lots of if (loading) {} code that plagues many of our components and makes orchestration and re-use of them a bit more painful than we'd like. I see lots of power in the idea of suspense as a way to orchestrate various generic async operations, but it feels like they don't want us to build solutions on this abstraction unless we buy into some opinionated framework. I can't really tell my team "let's use remix now lol".
All that being said this is a tremendous step forward and I'm looking forward to seeing what problems the React team tackles next.
>It's interesting to see how the APIs have changed over time—I'm sure as a result of some tough lessons learned at Facebook.
Oh yeah definitely. For history nerds, I've included a bunch of old (but relevant) PRs in the full changelog so that you can see the evolution. For example:
>Add useTransition and useDeferredValue to separate urgent updates from transitions. (#10426, #10715, #15593, #15272, #15578, #15769, #17058, #18796, #19121, #19703, #19719, #19724, #20672, #20976 by @acdlite, @lunaruan, @rickhanlonii, and @sebmarkbage)
>I'm curious if the SuspenseList API is making the cut here or if it's still on the roadmap? I played with it a while back and thought it was very cool, albeit slightly niche perhaps.
We've postponed it because there were some gaps we need to figure out. But it's likely coming in one of the minor releases.
>I see lots of power in the idea of suspense as a way to orchestrate various generic async operations, but it feels like they don't want us to build solutions on this abstraction unless we buy into some opinionated framework. I can't really tell my team "let's use remix now lol".
Hear, hear. The reason we suggest that is that implementing refetching in the data layer is currently too challenging. Relay implemented it, but it is pretty opinionated about other things so it's easier for Relay. Next.js doesn't currently support refetching for getServerSideProps anyway, so it wouldn't be a regression. But for a generic non-framework API, this feature is very important. We're working on a cache mechanism that might solve this, but it's work in progress and it's hard to provide guarantees that it'll ship in the same form as it is now. We just don't have all the answers yet.
Thanks for the links! Will certainly check them out, might even send me down memory lane a bit when I was first reading about these. Would love a full-fledged recap at some point—it's really interesting getting insight into the the internal mechanics of the problems my UI framework solves for me in my day-to-day. I always come away feeling more informed when you write something, but you've earned a long break after this release, so no pressure!
I hear you on the data fetching and always appreciate your teams' cautious approach. It gives me a lot of confidence in the APIs you all end up landing on, and I appreciate the focus on backwards compatibility and incremental upgrading as opposed to shipping out the first iteration of a cool idea that comes to mind. I know just enough about React to probably shoot myself in the foot with this type of stuff, but add in the idea of concurrency and all that likely falls over.
I think the story here with Relay and GraphQL is really awesome. I hope the Relay team has an article in the future showing off some of the possibilities—I think it makes a really strong argument for itself in conjunction with these features, even taking into account the restrictions you mention. Showing how some of these features flesh out in a more complete framework would be helpful in framing them in a vacuum. Or maybe I'll stop complaining and explore and write something myself!
If your team's using React Router, there's an upcoming release that aims to address the problem you describe (taken from Remix, as it's by the same guys): https://remix.run/blog/remixing-react-router
Thanks for the link! Hadn't seen that release, looks promising. I think this could definitely work for some of our newer apps that haven't fully bought into GraphQL yet. Not sure if the loader / action prop callbacks will be sufficient when you start getting into more complicated GraphQL use cases around caching. Haven't played with it though, so might be wrong! Good to see that these will already be in place for the community to leverage.
I wonder how concurrent mode in React stacks up with Solid.js. It seems React has been adding more and more features + complexity, while other frameworks are re-thinking the approach from the ground up building a simpler and faster primitive, yet keeping the same jsx primitives.
We've heard rumblings that react18 implies the need for major changes in legacy projects. For instance, jest testing suites apparently need to move away from enzyme?
Also, is there something about MUI and react18 that makes styled-components more of a pain? Not sure where I heard that.
Regarding styled-components and many similar CSS-in-JS libraries, I don't think there are any breaking changes currently with React 18, but it does seem like the writing is on the wall that React intends to not support libraries that inject styles into <style> tags, or at least has some specific rules these libraries need to follow to avoid performance problems. See this discussion: https://github.com/reactwg/react-18/discussions/110
I wouldn't say we're planning to not support them. They work with React 18. If they move to useInsertionEffect they'll avoid major performance issues.
The writing on the wall is more that we wouldn't encourage this mechanism over time because we find that <link> + inline styles have much better performance tradeoffs. Often, it's possible to implement a very similar API but statically extractable. That's great and we encourage that. But we wouldn't add a runtime helper like css() into React because we don't think this pattern scales well. Of course, we can't stop people from using it though.
I'm wondering how switching from a css-in-js library to <link> + inline styles would impact CLS. With css-in-js we have some built-in CLS protection in that I think it blocks the JS until the CSS is present, by definition. At the least, it sounds like <link> + inline styles would take more analysis effort to determine what the critical css is for any component.
CSS-in-JS and external <link> style sheets are not mutually exclusive.
There are a few toolkits out there that let you write component-oriented CSS-in-JS, but during build will extract everything to static external style sheets.
Thanks Dan - can you or anyone else point to something that details those performance tradeoffs in more detail? I think some of it has to do with css render-blocking when it's part of the JS.
Yes, thanks - after reading it more in depth. :) The "Future" section especially. I don't relish rewriting a legacy codebase that relies heavily upon css-in-js, hopefully the libraries will add compatibility.
Enzyme has been lagging in support for React features for several years now, so yes, I would expect it would not correctly support React 18 right away. (Note that both Enzyme and React Testing Library are independent of what test runner you're using - Jest, Mocha, etc).
> I would expect it would not correctly support React 18 right away
It's worse than you know, Enzyme will never support React 18, and it will likely never officially (or fully) support React 17. It's a completely dead project.
(Honestly I’m a bit surprised some big company hasn’t taken over Enzyme development - there most be teams facing hundreds ,or thousands, of hours on test rewriting)
Not sure what Enzyme's plans are, since I know they depend on some React internals.
However, we've worked closely with the React Testing Library maintainers, and that's the solution I'd recommend for React tests going forward. We're fans of RTL because it encourages you to write tests "end-2-end"-like tests that resemble real-world scenarios and are resilient to implementation changes.
That's a shame, because there are plenty of use cases where testing a shallow render makes much more sense than fully rendering the component—for example, when you're wrapping a third-party library and simply need to test that the correct props are being passed, instead of testing the library's functionality.
Sure, but using Enzyme has been easier and far less brittle in my experience by being less reliant on hacky, library-specific mocking techniques. (Then again, I suppose you could argue that Enzyme is itself a giant hack, but it worked very well for me in the past.)
Congratulations to the React team! I remember three years ago when Dan first showcased some of the concurrent features [1], so this has been quite long in the making.
Exciting to see so much server-side focus in all recent development. IMO React has massive value outside of the usual static site or SPA making API calls use cases. Eagerly waiting for Server Components to get ready.
When is the Suspense documentation going to be updated? I don't see it in the beta docs, and the main documentation page is for v17, so its still marked as experimental. It also says that, "Before React 18 is released, we will replace this page with stable documentation."
I was really hoping that they would have internal implementation by now to automatically infer the missing dependencies array for hooks so we need not rely on an external linting tool. This is one of the most common issues faced by react devs.
Really excited about the transitions (edit: I mean batching) for state updates. I always found it so frustrating that updating 3 different state values in a callback would cause 3 separate renders.
If you have a list of elements rendered in a container (from array), does React always re-render the whole thing (contents of container) when adding / removing elements from the array or is there a way to work around that? I'm coming from Svelte, I would not be learning React if it was not for its omni-presence in the job market and I'm genuinely curious.
Yes. React re-renders components recursively by default. So, any state update in a parent component will recurse through and render all child components. But, a "render" does not necessarily imply a "DOM update" - it's about asking the components "what do you want the UI to look like now?", and determining _if_ updates are needed. This can be optimized if needed.
React will nag you to give the array elements unique keys so that it can track them. If you do that, it will generally be able to avoid manipulating the DOM for those elements of the array that did not change. It will still render (= execute the JS of the component) all of them by default, how expensive that is depends entirely on the content of your components.
If that is a problem you can use React.memo() to prevent rerendering of those components if their inputs did not change.
Well, it's only efficient if the component which renders each element in the list gets a stable key AND is React.memo() AND the props passed to the components do not make the React.memo() pointless.
For example the following will not be particularly efficient, because a fresh callback is passed to the component on each render.
React will iterate over the whole array again (the array causes the container component to re-render, and its contents including the JSX are just JS that gets run again), but the individual components rendered from the array can prevent their own internal render logic from being called again unnecessarily by using React.memo
Sorry to hear that. Did you report the issues? Generally it's hard to fix bugs in a release candidate if the bugs get unreported. If you file a bug we can have a look.
@danabramov would you mind sharing the rationale behind making the ReactWG invite only? I understand that, de jure, it's Facebook's property, and you all can do whatever you want with it. De facto, since so many people on the outside world contributed to the project, at least an election of a commission would have been warranted. Would you mind commenting?
The Transitions look nice but I feel like this will bloat code incredibly. Maybe it‘s meant only as an optimisation to be used sparingly but if I would always have to also start a transition when I do some conditional rendering it will generate a lot of overhead code. Or am I wrong?
We don't expect most users will interact with the `startTransition` API directly. Instead, it will be built into routing libraries and other infra code so you get the benefit of transitions without need to wrap all the state updates yourself.
Yet again, another React major version, more churn in the ecosystem. Are all of the libraries your app depends on compatible with the new version? How much effort to update the ones that aren't, if that's even possible? Get ready to spend tens of your team's man-hours answering these questions.
Ah yes, I often forget that the JavaScript ecosystem invented versions. We really should have taken a page from literally every other programming framework that has never had these problems.
what is the point of this comment? would you prefer react never receive any updates? AFAIK transitioning to react 18 shouldn't break much unless you want to take advantage of concurrent mode
It's a fair criticism! From our point of view, this is not really true if you consider the scope of the problems that are being solved. Sure, React itself was very simple, but implementing common patterns (like code splitting, coordinating loading indicators) was difficult, and some things (like streaming HTML while waiting for data) were downright impossible. If you compare React today vs old React + all the stuff you have to add for this, you might find that React today gains a lot of powerful features from very few primitives (like startTransition and Suspense). It might read densely in a blog post though, I get that.
"The most important addition in React 18 is something we hope you never have to think about: concurrency." - really? this is what our technical prowess has come to?
Creating an abstraction that allows you to write seemingly imperative code but have it actually executed concurrently is a huge technical achievement in any area. “Fearless” concurrency is the only concurrency paradigm that scales and no one has solved it.
Congratulations, but
to me React is like Rust. Something I always wanted to get into but found better alternatives.
In the react case Vue wins for me and in the Rust case it's Go.
I really tried, time and time again to like it and write something with it, but Vue just offers the better libraries. Altough with the recent 2 to 3 upgrade and pinia instead of vuex I'm starting to get dissatisfied with the "no single proper way" of Vue. Vuex-orm being the best frontend REST wired ORM, nothing comes close to ease of use and setup.
Meanwhile react has what? Complicated redux, or is that even a thing anymore? Idk, which I would. Redux the boilerplate abomination. That's exactly what drove me away from Angular.
But I'm starting to rant again.
And react has even more of the "not a single proper way". Yeah I know, nextjs the magic bullet, but what if you don't agree with pretty much everything about it, starting with routing.
I've worked both on large Vue and react projects. Wouldn't pick myself Vue ever if I have the choice.
Vue is certainly easier to learn, and comes with a lot of oficial libraries such as vuex, Vue router etc. But that's all about it.
The Vue 2 to 3 transition is a big fuck up, python level. One of the companies I've worked for will never be able to migrate to Vue 3, because they cannot afford to stop product development and they also have a ton of external dependencies that are mostly abandoned.
The integration with typescript, even in Vue 3 is still not as good as it is for react. This is critical for large projects, and to have proper ide autocomopletion, etc.
Then the ecosystem....it is a lot smaller than the React ecosystem.
Then the "meta frameworks". Next.js is infinitely better and better managed than Nuxt, which went full rewrite and again, from my point of view that's a big fuck up.
And finally, I have absolutely nothing against other languages (even English is not my native language) but I got really tired of finding myself debugging problems and ending up in issues, forums or readmes in languages that are not English (mostly Chinese).
React has its drawbacks, but I prefer those by a far amount to the drawbacks of using Vue.
> to me React is like Rust. Something I always wanted to get into but found better alternatives.
That's funny. To me it's the other way. I love both React and Rust. Vue and Go both seem like tools that get halfway to the benefits of React/Rust and would be good choices if React and Rust weren't available.
> Meanwhile react has what? Complicated redux, or is that even a thing anymore? Idk, which I would. Redux the boilerplate abomination.
There is now redux-toolkit, an official part of the redux project that provides a standard convention and helper within redux that reduces that boilerplate. There's also mobX which is more like Vue's state management. Both are well supported.
FWIW, our official Redux Toolkit package solved the "boilerplate" concerns, including our new RTK Query data fetching API.
If you're happy with Vue, great! If you do get a chance, though, please take a look at the Redux docs tutorials to see how we teach writing "modern Redux" code today:
React and OpenAPI are orthogonal things. You'd build a JavaScript/TypeScript library for talking to an API, not a React one.
(Generally, though it adds some friction unless you have HTTP servers with libraries to help you out, I prefer this approach whenever possible to GraphQL. Mostly because relying on frontend folks to inflict terrible damage to databases via wild abuse of resolvers is not my cup of tea, but as GraphQL tools become smarter I'm coming around on this a bit.)
The Working Group model really helped us in the community give feedback - APIs like `useSyncExternalStore` wouldn't have happened otherwise, and I really appreciate the responsiveness on that topic.
FWIW, React-Redux v8 is in beta right now:
- https://github.com/reduxjs/react-redux/releases
I think it's basically ready to go, but I haven't had a chance to really test out the SSR support I added a couple months ago. I'd love to have some help testing that out.
v7 will _run_ with React 18, but v8 has been specifically reworked to behave correctly when used with React's new "Concurrent Rendering" capabilities. We've also converted React-Redux itself to TS (no more separate types package).
Ideally, I'd like to release v8 as final in the next week or two.