RFC-78: Dropping support for React 16 and rendering in a React 18 concurrent root in Jira and Confluence

RFCs are a way for Atlassian to share what we’re working on with our valued developer community.

It’s a document for building shared understanding of a topic. It expresses a technical solution, but can also communicate how it should be built or even document standards. The most important aspect of an RFC is that a written specification facilitates feedback and drives consensus. It is not a tool for approving or committing to ideas, but more so a collaborative practice to shape an idea and to find serious flaws early.

Please respect our community guidelines: keep it welcoming and safe by commenting on the idea not the people (especially the author); keep it tidy by keeping on topic; empower the community by keeping comments constructive. Thanks!


Project Summary

As many of you noticed, Atlaskit packages started supporting React 18 more than a year ago and we’ve made massive progress in that time and have a full update on plans for supporting different versions of React and the impact of this rollout on our partners and ecosystem.

Problem

While many of you are already on React 18, this may have an impact in some scenarios, and we’d like to know how we can best land this project.

We’re going through this migration for a lot of reasons, but to say the top-of-mind:

  1. To directly improve and unblock future opportunities to improve the performance our own products and ultimately we’re aiming to improve the experience for our customers.
  2. It’s what we all want—developers, ourselves and our partners, want to work with modern technology and not be held back by outdated versions.

However, this has been a lengthy migration as React 17, React 18, and React 18’s new APIs have added complexity and breaking changes that had to be solved foundationally and tested internally before any timelines were known.

It’s worth saying something given React 19 has gone stable that we’re aware that migration will be even more complex. We have no current plans with React 19, but this project has been a massive step in the right direction and we should all consider the APIs being removed in React 19 fully deprecated to make a future migration more simple.

Proposed solution

The current state of our support for React versions is as follows:

  • React 16 and React 17 have been deprecated internally for some time now as most of our key products are running on React 18 with the legacy render
  • More than 90% of applicable Atlaskit packages currently support React 18, as denoted via their package.json’s peerDependencies
  • We’re currently focused on supporting the new React 18 createRoot API (modern aka concurrent rendering), as products look to utilize it

With this, our products are now able to tap into React 18’s new features which I’ll divide into two plans going forward, both which may have some impact on ecosystem apps.

We’re formally dropping support for React 16 and React 17

Today, more than 90% of the maintained packages in our public @atlaskit/* scope support React 18. Refer to each package’s peerDependencies entry as the source-of-truth for that support.

  • If a package does not currently have support listed, they have already been asked internally and this is expected in the next few months for packages used in these products
  • If a package supports it and you experience an issue, consider it a bug report like any other! There are a few known issues with concurrent rendering being resolved currently

In the coming months, we’re looking to drop intentional support for React 16 and 17 for packages in the @atlaskit/* scope. The main technical change here is our packages will no longer be tested through automated CI in a React 16.8 environment as they are today, and instead everything will run in a React 18 concurrent environment, where possible.

For most maintained packages in this @atlaskit/* scope, the peerDependencies will be updated to reflect it only supports React 18 in the near future, signifying that release.

We don’t expect to make breaking changes overnight as we’ll limit the use of new APIs to be backwards-compatible as this change will have internal and ecosystem impacts. However, without CI running on these versions, we can’t guarantee changes these don’t creep in, especially through third-party dependency upgrades, so future versions may be gated by a React 18 upgrade.

Timeline:

  • Currently: Atlaskit packages are still migrating to support React 18 — we’re above 90% support as of writing. A very tiny amount of packages still have bug fixes hidden behind internal feature flags meaning they don’t fully support React 18 concurrency which we’re hoping will be unblocked prior to our full releases.
  • From January 2025: Expect major versions of packages to drop support via peerDependencies, signifying we’re no longer testing those on React 16
  • By February 2025: All Atlaskit packages used in Jira and Confluence are expected to support React 18 and concurrency
  • By July 2025: All Atlaskit packages that are actively maintained are expected to support React 18 and concurrency

Your apps may be rendered inside a React 18 concurrent root

As early as January 2025, the cloud versions of Confluence and Jira will start rendering content inside of the new ReactDOM.createRoot and ReactDOM.hydrateRoot concurrent APIs and possibly the ReactDOM.renderToPipeableStream API after that.

We’re currently undergoing multi-quarter effort to uplift and test these new APIs internally and while we finish that, we’re looking to see if there’s any concerns on the wider ecosystem partners.

  • For Connect and Forge Custom UI Apps: while we’ve resolved an internal issue with event bubbling, no impact is expected as you maintain your own root and React version
  • For Forge UI Kit Apps: there’s a chance of breaking changes from either the React 17 event bubbling change or with React 18’s concurrent rendering where renders may be batched or even discarded Edit: at this point, no update to the Forge UI Kit reconcilier is planned, this was misunderstood. Same “no impact is expected” for Forge UI Kit Apps.

Timeline:

  • Currently: Working through internal support for Atlaskit, Jira, and Confluence to support React 18 and React 18 createRoot and hydrateRoot, followed by renderToPipeableStream in the future
  • From January 2025: Users will start being served content rendered with the React 18 createRoot and hydrateRoot concurrent API in Jira and Confluence (through separate rollouts), and your ecosystem apps may be rendered into that environment

These rollouts may take months to land in full and will be thoroughly tested through internal dogfooding before customers see them and we will take care to investigate and review this RFC’s feedback and adjust where necessary.

Asks

You’ve been asking us for React 18 and even though we’ve been a bit quiet and internalized this until now, Atlassian has been very committed to landing this—for our partners, our developers, and our customers.

What we need is to know how we best support our partners with this project. Tell us if there’s anything to investigate and explore or if there’s any missed concerns we should answer and we will take this into immediate consideration and planning.

Going forward:

  • Recommended action: If you haven’t already, please migrate your app to React 18 and turn on createRoot concurrency in your local and testing environments! Our packages should support you now, or soon.
    • It’s also suggested that you action the deprecations and guidance that the React team suggest (eg. in the React 19 migration guide), as they will go away in future versions and may be a problem in concurrent rendering.
  • Supporting you: If you’ve encountered specific issues on the latest version of our packages that say they support React 18 or have a specific package that’s missing React 18 support, please create a new topic and we will triage them like any other bug.
14 Likes

Out of curiosity: AFAIK all apps render within an iframe, right? How does this impact Connect/Forge apps?

7 Likes
  • For Forge UI Kit Apps: there’s a chance of breaking changes from either the React 17 event bubbling change or with React 18’s concurrent rendering where renders may be batched or even discarded

Can you expand on what this means, and more importantly, whether a simple dependency update will address this, if need be?

After all, one core value proposition of UI Kit is that we are (mostly) shielded from such intricacies, so it’s slightly surprising that Connect and Custom UI are not affected, yet UI Kit is :thinking:

1 Like

Our packages should support you now, or soon.

The latest version of @atlaskit/focus-ring, @atlaskit/button, @atlaskit/css-reset, and a host of others don’t support React 18 and require the developer to force override peer dependencies in order to build. I do not understand how you can recommend that developers upgrade to a version of React that your basic button component does not support.

@atlaskit/analytics-next is a transitive dependency of pretty much the whole Atlassian UI Toolkit, and throws console errors because childContextTypes is deprecated in React 18 and totally prevents migration to React 19. Please take your own advice and address deprecations in your toolkit code.

I also do not understand why you are asking your developer partners to open bug reports for basic package hygiene in Atlaskit. Unless you’re opening up atlaskit to open source contributions, it is not incumbent on the community to validate your code for you.

We are working hard to enhance the functionality of Atlassian products with our partner products, and value our relationship with Atlassian, but this RFC makes no sense unless and until building Atlassian UI projects for React 18 is fully supported with no glaring console errors and without overriding peer dependencies at the very least.

3 Likes

@remie @sopel Upon further discussion actually, while Forge UI Kit Apps use a controlled React reconciler, the team doesn’t have any immediate plans to turn on concurrency. I will update to reflect this as it currently doesn’t match the same timeline as noted.

Additionally, it is worth saying that even if the Forge UI Kit reconciler was turned onto concurrency, the impact is relatively low and you’re typically shielded from this—it’s just patterns that explicitly require synchronous renders that could be affected.

1 Like

@scottjackson By asking our partners to report issues with our packages, I mean that most of these packages have been running on React 18 in products for months (some packages more than a year) and we fully expect them to work, or have a final change or feature flag rollout waiting to land. We’re not asking to crowdsource testing, but rather we’re just looking to find any gaps and edge-cases, if we’ve missed anything in our internal testing so far.

Particularly, we haven’t been bothered by the peerDependencies and they have no impact on our development lifecycle and would suggest they are ignored by ecosystem for now as well—but are we missing other things?

@atlaskit/analytics-next is one of those where the majority of packages don’t use invoke that childContextTypes legacy context path (eg. @atlaskit/button should not), and we’re testing removing that entire code path via a feature flag (that legacy context is not used in Jira or Confluence for example). That may not fully solve your concerns as @atlaskit/analytics-next-stable-react-context package does not denote the correct peerDependencies—I’d highly suggest ignoring that mismatch, but I will look into options as bumping this singleton context package has concerns.

… until building Atlassian UI projects for React 18 is fully supported …

This is a very fine balance for us—do we involve you before we’ve done this work when we have nothing to test or show, or after we’ve done it when there’s little room for change? We’re not completely done, but we’re still choosing to share as we have the capacity to react to concerns and solve problems before the changes land in full.

So you are telling us that we should add overrides in our package.json?

I’m just not convinced that this is proper package stewardship. These are public packages deployed to NPM for use by 3rd parties. You wouldn’t expect Babel to just tell you to ignore some incorrect peer dependencies, right?

As soon as Atlassian decided to put these packages out for use by external consumers, the responsibility for managing these packages has changed and should not include methods usually acceptable for internal use only.

5 Likes

Yes, at least during this stage in these timelines, I would say to use React 18 (or if you’ve been using it for a while now), you would have to ignore these warnings and that many mean installing via npm install --legacy-peer-deps (etc) depending on your setup. This isn’t ideal for us, or our partners, but with thousands of transitive dependencies (many being third-party as well), iteration in this area is required.

Our focus is on safely landing the functionality and benefits of React 18 and concurrency to unblock both Ecosystem apps and our product’s performance alongside allowing for wider access to the modern React ecosystem.

Beyond that, we will chip away at things like StrictMode compliance and other signals to enable React 19 and prevent regressions, but peerDependencies is only one of those signals we use to measure success that will be chipped away and resolved over time—often while we’re executing on the customer-facing and developer-facing improvements that we’re prioritizing.

--legacy-peer-deps’s blast radius isn’t limited to our Atlaskit packages, it’s not telling npm to ignore enforcement for only certain packages, it’s telling it to ignore enforcement for the whole web application. That’s really sort of the nuclear option.

If you want to involve your community in testing upgrades, just dist-tag @stable for what you’re confident about and @next for what you want tested. For example, if you’re not quite ready to make @atlaskit/analytics-next at version 10 into something that supports React 18, then tag it stable and tag version 11 or 12 or something next.

This would also require addressing the fact that 10.2.0 is marked latest and 9.1.3 is marked next currently but, you know, multiple problems can be solved here.

I will say, though, @atlaskit/analytics-next does recite the correct peer dependency at 10.2.0: Bitbucket

However, it still throws console errors.

Warning: AnalyticsContext uses the legacy childContextTypes API which is no longer supported and will be removed in the next major release. Use React.createContext() instead

.Learn more about this warning here: https://reactjs.org/link/legacy-context Error Component Stack
    at AnalyticsContext (LegacyAnalyticsContext.js:46:20)
    at ExportedAnalyticsContext (<anonymous>)
3 Likes

I have been googling the overrides option that Remie mentioned above. If I add the following in my package.json, the peer dependency warnings from @atlaskit/analytics-next-stable-react-context are hidden without having to tag every npm command with --legacy-peer-deps:

{
  ...,
  "overrides": {
    "@atlaskit/analytics-next-stable-react-context": {
      "react": "18.3.1"
    }
  }
}

Reference: node.js - How do I override nested NPM dependency versions? - Stack Overflow

I would also prefer not to do this. Still, it is better than typing --legacy-peer-deps each command, and from what I understand, this only applies to this particular dependency, so the effect is relatively contained.

4 Likes

Yeah, we will likely explore setting that exact overrides on @atlaskit/analytics-next ourselves as we run through this large list of components as directly bumping @atlaskit/analytics-next-stable-react-context may have larger impacts for our customers and ecosystem that we can’t control.

1 Like

Those are great news up there.

I have question regarding React 19. Are there any plans for @atlaskit to support react19 anytime soon?

Or rather if we’ll have an ability to use the packages in react19 project?

I put a note about this in the RFC, but I can definitely say that React 19 won’t work today for many or most packages due to a few LegacyContext we’re working on deleting and mostly third-party packages that have legacy APIs. I hope we chip away at this enough that it becomes viable in the future.

It’s worth saying something given React 19 has gone stable that we’re aware that migration will be even more complex. We have no current plans with React 19, but this project has been a massive step in the right direction and we should all consider the APIs being removed in React 19 fully deprecated to make a future migration more simple.

2 Likes