• maiweb v0.1.0
  • ★
  • Feedback

reactjs.org

Visit site ↗

All items hosted on this domain, most recent first.

  • React Blog reactjs.org framework javascript react technology web-dev web-development 2022-06-15 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. React 18 was years in the making, and with it brought valuable lessons for the React team. Its release was the result of many years of research and exploring many paths. Some of those paths were...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    React 18 was years in the making, and with it brought valuable lessons for the React team. Its release was the result of many years of research and exploring many paths. Some of those paths were successful; many more were dead-ends that led to new insights. One lesson we’ve learned is that it’s frustrating for the community to wait for new features without having insight into these paths that we’re exploring.

    We typically have a number of projects being worked on at any time, ranging from the more experimental to the clearly defined. Looking ahead, we’d like to start regularly sharing more about what we’ve been working on with the community across these projects.

    To set expectations, this is not a roadmap with clear timelines. Many of these projects are under active research and are difficult to put concrete ship dates on. They may possibly never even ship in their current iteration depending on what we learn. Instead, we want to share with you the problem spaces we’re actively thinking about, and what we’ve learned so far.

    Server Components

    We announced an experimental demo of React Server Components (RSC) in December 2020. Since then we’ve been finishing up its dependencies in React 18, and working on changes inspired by experimental feedback.

    In particular, we’re abandoning the idea of having forked I/O libraries (eg react-fetch), and instead adopting an async/await model for better compatibility. This doesn’t technically block RSC’s release because you can also use routers for data fetching. Another change is that we’re also moving away from the file extension approach in favor of annotating boundaries.

    We’re working together with Vercel and Shopify to unify bundler support for shared semantics in both Webpack and Vite. Before launch, we want to make sure that the semantics of RSCs are the same across the whole React ecosystem. This is the major blocker for reaching stable.

    Asset Loading

    Currently, assets like scripts, external styles, fonts, and images are typically preloaded and loaded using external systems. This can make it tricky to coordinate across new environments like streaming, server components, and more. We’re looking at adding APIs to preload and load deduplicated external assets through React APIs that work in all React environments.

    We’re also looking at having these support Suspense so you can have images, CSS, and fonts that block display until they’re loaded but don’t block streaming and concurrent rendering. This can help avoid “popcorning“ as the visuals pop and layout shifts.

    Static Server Rendering Optimizations

    Static Site Generation (SSG) and Incremental Static Regeneration (ISR) are great ways to get performance for cacheable pages, but we think we can add features to improve performance of dynamic Server Side Rendering (SSR) – especially when most but not all of the content is cacheable. We’re exploring ways to optimize server rendering utilizing compilation and static passes.

    React Optimizing Compiler

    We gave an early preview of React Forget at React Conf 2021. It’s a compiler that automatically generates the equivalent of useMemo and useCallback calls to minimize the cost of re-rendering, while retaining React’s programming model.

    Recently, we finished a rewrite of the compiler to make it more reliable and capable. This new architecture allows us to analyze and memoize more complex patterns such as the use of local mutations, and opens up many new compile-time optimization opportunities beyond just being on par with memoization hooks.

    We’re also working on a playground for exploring many aspects of the compiler. While the goal of the playground is to make development of the compiler easier, we think that it will make it easier to try it out and build intuition for what the compiler does. It reveals various insights into how it works under the hood, and live renders the compiler’s outputs as you type. This will be shipped together with the compiler when it’s released.

    Offscreen

    Today, if you want to hide and show a component, you have two options. One is to add or remove it from the tree completely. The problem with this approach is that the state of your UI is lost each time you unmount, including state stored in the DOM, like scroll position.

    The other option is to keep the component mounted and toggle the appearance visually using CSS. This preserves the state of your UI, but it comes at a performance cost, because React must keep rendering the hidden component and all of its children whenever it receives new updates.

    Offscreen introduces a third option: hide the UI visually, but deprioritize its content. The idea is similar in spirit to the content-visibility CSS property: when content is hidden, it doesn’t need to stay in sync with the rest of the UI. React can defer the rendering work until the rest of the app is idle, or until the content becomes visible again.

    Offscreen is a low level capability that unlocks high level features. Similar to React’s other concurrent features like startTransition, in most cases you won’t interact with the Offscreen API directly, but instead via an opinionated framework to implement patterns like:

    • Instant transitions. Some routing frameworks already prefetch data to speed up subsequent navigations, like when hovering over a link. With Offscreen, they’ll also be able to prerender the next screen in the background.
    • Reusable state. Similarly, when navigating between routes or tabs, you can use Offscreen to preserve the state of the previous screen so you can switch back and pick up where you left off.
    • Virtualized list rendering. When displaying large lists of items, virtualized list frameworks will prerender more rows than are currently visible. You can use Offscreen to prerender the hidden rows at a lower priority than the visible items in the list.
    • Backgrounded content. We’re also exploring a related feature for deprioritizing content in the background without hiding it, like when displaying a modal overlay.

    Transition Tracing

    Currently, React has two profiling tools. The original Profiler shows an overview of all the commits in a profiling session. For each commit, it also shows all components that rendered and the amount of time it took for them to render. We also have a beta version of a Timeline Profiler introduced in React 18 that shows when components schedule updates and when React works on these updates. Both of these profilers help developers identify performance problems in their code.

    We’ve realized that developers don’t find knowing about individual slow commits or components out of context that useful. It’s more useful to know about what actually causes the slow commits. And that developers want to be able to track specific interactions (eg a button click, an initial load, or a page navigation) to watch for performance regressions and to understand why an interaction was slow and how to fix it.

    We previously tried to solve this issue by creating an Interaction Tracing API, but it had some fundamental design flaws that reduced the accuracy of tracking why an interaction was slow and sometimes resulted in interactions never ending. We ended up removing this API because of these issues.

    We are working on a new version for the Interaction Tracing API (tentatively called Transition Tracing because it is initiated via startTransition) that solves these problems.

    New React Docs

    Last year, we announced the beta version of the new React documentation website. The new learning materials teach Hooks first and has new diagrams, illustrations, as well as many interactive examples and challenges. We took a break from that work to focus on the React 18 release, but now that React 18 is out, we’re actively working to finish and ship the new documentation.

    We are currently writing a detailed section about effects, as we’ve heard that is one of the more challenging topics for both new and experienced React users. Synchronizing with Effects is the first published page in the series, and there are more to come in the following weeks. When we first started writing a detailed section about effects, we’ve realized that many common effect patterns can be simplified by adding a new primitive to React. We’ve shared some initial thoughts on that in the useEvent RFC. It is currently in early research, and we are still iterating on the idea. We appreciate the community’s comments on the RFC so far, as well as the feedback and contributions to the ongoing documentation rewrite. We’d specifically like to thank Harish Kumar for submitting and reviewing many improvements to the new website implementation.

    Thanks to Sophie Alpert for reviewing this blog post!

  • React Blog reactjs.org framework javascript react technology web-dev web-development 2022-03-29 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. React 18 is now available on npm! In our last post, we shared step-by-step instructions for upgrading your app to React 18. In this post, we’ll give an overview of what’s new in React 18, and what...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    React 18 is now available on npm!

    In our last post, we shared step-by-step instructions for upgrading your app to React 18. In this post, we’ll give an overview of what’s new in React 18, and what it means for the future.

    Our latest major version includes out-of-the-box improvements like automatic batching, new APIs like startTransition, and streaming server-side rendering with support for Suspense.

    Many of the features in React 18 are built on top of our new concurrent renderer, a behind-the-scenes change that unlocks powerful new capabilities. Concurrent React is opt-in — it’s only enabled when you use a concurrent feature — but we think it will have a big impact on the way people build applications.

    We’ve spent years researching and developing support for concurrency in React, and we’ve taken extra care to provide a gradual adoption path for existing users. Last summer, we formed the React 18 Working Group to gather feedback from experts in the community and ensure a smooth upgrade experience for the entire React ecosystem.

    In case you missed it, we shared a lot of this vision at React Conf 2021:

    • In the keynote, we explain how React 18 fits into our mission to make it easy for developers to build great user experiences
    • Shruti Kapoor demonstrated how to use the new features in React 18
    • Shaundai Person gave us an overview of streaming server rendering with Suspense

    Below is a full overview of what to expect in this release, starting with Concurrent Rendering.

    Note for React Native users: React 18 will ship in React Native with the New React Native Architecture. For more information, see the React Conf keynote here.

    What is Concurrent React?

    The most important addition in React 18 is something we hope you never have to think about: concurrency. We think this is largely true for application developers, though the story may be a bit more complicated for library maintainers.

    Concurrency is not a feature, per se. It’s a new behind-the-scenes mechanism that enables React to prepare multiple versions of your UI at the same time. You can think of concurrency as an implementation detail — it’s valuable because of the features that it unlocks. React uses sophisticated techniques in its internal implementation, like priority queues and multiple buffering. But you won’t see those concepts anywhere in our public APIs.

    When we design APIs, we try to hide implementation details from developers. As a React developer, you focus on what you want the user experience to look like, and React handles how to deliver that experience. So we don’t expect React developers to know how concurrency works under the hood.

    However, Concurrent React is more important than a typical implementation detail — it’s a foundational update to React’s core rendering model. So while it’s not super important to know how concurrency works, it may be worth knowing what it is at a high level.

    A key property of Concurrent React is that rendering is interruptible. When you first upgrade to React 18, before adding any concurrent features, updates are rendered the same as in previous versions of React — in a single, uninterrupted, synchronous transaction. With synchronous rendering, once an update starts rendering, nothing can interrupt it until the user can see the result on screen.

    In a concurrent render, this is not always the case. React may start rendering an update, pause in the middle, then continue later. It may even abandon an in-progress render altogether. React guarantees that the UI will appear consistent even if a render is interrupted. To do this, it waits to perform DOM mutations until the end, once the entire tree has been evaluated. With this capability, React can prepare new screens in the background without blocking the main thread. This means the UI can respond immediately to user input even if it’s in the middle of a large rendering task, creating a fluid user experience.

    Another example is reusable state. Concurrent React can remove sections of the UI from the screen, then add them back later while reusing the previous state. For example, when a user tabs away from a screen and back, React should be able to restore the previous screen in the same state it was in before. In an upcoming minor, we’re planning to add a new component called <Offscreen> that implements this pattern. Similarly, you’ll be able to use Offscreen to prepare new UI in the background so that it’s ready before the user reveals it.

    Concurrent rendering is a powerful new tool in React and most of our new features are built to take advantage of it, including Suspense, transitions, and streaming server rendering. But React 18 is just the beginning of what we aim to build on this new foundation.

    Gradually Adopting Concurrent Features

    Technically, concurrent rendering is a breaking change. Because concurrent rendering is interruptible, components behave slightly differently when it is enabled.

    In our testing, we’ve upgraded thousands of components to React 18. What we’ve found is that nearly all existing components “just work” with concurrent rendering, without any changes. However, some of them may require some additional migration effort. Although the changes are usually small, you’ll still have the ability to make them at your own pace. The new rendering behavior in React 18 is only enabled in the parts of your app that use new features.

    The overall upgrade strategy is to get your application running on React 18 without breaking existing code. Then you can gradually start adding concurrent features at your own pace. You can use <StrictMode> to help surface concurrency-related bugs during development. Strict Mode doesn’t affect production behavior, but during development it will log extra warnings and double-invoke functions that are expected to be idempotent. It won’t catch everything, but it’s effective at preventing the most common types of mistakes.

    After you upgrade to React 18, you’ll be able to start using concurrent features immediately. For example, you can use startTransition to navigate between screens without blocking user input. Or useDeferredValue to throttle expensive re-renders.

    However, long term, we expect the main way you’ll add concurrency to your app is by using a concurrent-enabled library or framework. In most cases, you won’t interact with concurrent APIs directly. For example, instead of developers calling startTransition whenever they navigate to a new screen, router libraries will automatically wrap navigations in startTransition.

    It may take some time for libraries to upgrade to be concurrent compatible. We’ve provided new APIs to make it easier for libraries to take advantage of concurrent features. In the meantime, please be patient with maintainers as we work to gradually migrate the React ecosystem.

    For more info, see our previous post: How to upgrade to React 18.

    Suspense in Data Frameworks

    In React 18, you can start using Suspense for data fetching in opinionated frameworks like Relay, Next.js, Hydrogen, or Remix. Ad hoc data fetching with Suspense is technically possible, but still not recommended as a general strategy.

    In the future, we may expose additional primitives that could make it easier to access your data with Suspense, perhaps without the use of an opinionated framework. However, Suspense works best when it’s deeply integrated into your application’s architecture: your router, your data layer, and your server rendering environment. So even long term, we expect that libraries and frameworks will play a crucial role in the React ecosystem.

    As in previous versions of React, you can also use Suspense for code splitting on the client with React.lazy. But our vision for Suspense has always been about much more than loading code — the goal is to extend support for Suspense so that eventually, the same declarative Suspense fallback can handle any asynchronous operation (loading code, data, images, etc).

    Server Components is Still in Development

    Server Components is an upcoming feature that allows developers to build apps that span the server and client, combining the rich interactivity of client-side apps with the improved performance of traditional server rendering. Server Components is not inherently coupled to Concurrent React, but it’s designed to work best with concurrent features like Suspense and streaming server rendering.

    Server Components is still experimental, but we expect to release an initial version in a minor 18.x release. In the meantime, we’re working with frameworks like Next.js, Hydrogen, and Remix to advance the proposal and get it ready for broad adoption.

    What’s New in React 18

    New Feature: Automatic Batching

    Batching is when React groups multiple state updates into a single re-render for better performance. Without automatic batching, we only batched updates inside React event handlers. Updates inside of promises, setTimeout, native event handlers, or any other event were not batched in React by default. With automatic batching, these updates will be batched automatically:

    // Before: only React events were batched.
    setTimeout(() => {
      setCount(c => c + 1);
      setFlag(f => !f);
      // React will render twice, once for each state update (no batching)
    }, 1000);
    
    // After: updates inside of timeouts, promises,
    // native event handlers or any other event are batched.
    setTimeout(() => {
      setCount(c => c + 1);
      setFlag(f => !f);
      // React will only re-render once at the end (that's batching!)
    }, 1000);

    For more info, see this post for Automatic batching for fewer renders in React 18.

    New Feature: Transitions

    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.

    Urgent updates like typing, clicking, or pressing, need immediate response to match our intuitions about how physical objects behave. Otherwise they feel “wrong”. However, transitions are different because the user doesn’t expect to see every intermediate value on screen.

    For example, when you select a filter in a dropdown, you expect the filter button itself to respond immediately when you click. However, the actual results may transition separately. A small delay would be imperceptible and often expected. And if you change the filter again before the results are done rendering, you only care to see the latest results.

    Typically, for the best user experience, a single user input should result in both an urgent update and a non-urgent one. You can use startTransition API inside an input event to inform React which updates are urgent and which are “transitions”:

    import {startTransition} from 'react';
    
    // Urgent: Show what was typed
    setInputValue(input);
    
    // Mark any state updates inside as transitions
    startTransition(() => {
      // Transition: Show the results
      setSearchQuery(input);
    });

    Updates wrapped in startTransition are handled as non-urgent and will be interrupted if more urgent updates like clicks or key presses come in. If a transition gets interrupted by the user (for example, by typing multiple characters in a row), React will throw out the stale rendering work that wasn’t finished and render only the latest update.

    • useTransition: a hook to start transitions, including a value to track the pending state.
    • startTransition: a method to start transitions when the hook cannot be used.

    Transitions will opt in to concurrent rendering, which allows the update to be interrupted. If the content re-suspends, transitions also tell React to continue showing the current content while rendering the transition content in the background (see the Suspense RFC for more info).

    See docs for transitions here.

    New Suspense Features

    Suspense lets you declaratively specify the loading state for a part of the component tree if it’s not yet ready to be displayed:

    <Suspense fallback={<Spinner />}>
      <Comments />
    </Suspense>

    Suspense makes the “UI loading state” a first-class declarative concept in the React programming model. This lets us build higher-level features on top of it.

    We introduced a limited version of Suspense several years ago. However, the only supported use case was code splitting with React.lazy, and it wasn’t supported at all when rendering on the server.

    In React 18, we’ve added support for Suspense on the server and expanded its capabilities using concurrent rendering features.

    Suspense in React 18 works best when combined with the transition API. If you suspend during a transition, React will prevent already-visible content from being replaced by a fallback. Instead, React will delay the render until enough data has loaded to prevent a bad loading state.

    For more, see the RFC for Suspense in React 18.

    New Client and Server Rendering APIs

    In this release we took the opportunity to redesign the APIs we expose for rendering on the client and server. These changes allow users to continue using the old APIs in React 17 mode while they upgrade to the new APIs in React 18.

    React DOM Client

    These new APIs are now exported from react-dom/client:

    • createRoot: New method to create a root to render or unmount. Use it instead of ReactDOM.render. New features in React 18 don’t work without it.
    • hydrateRoot: New method to hydrate a server rendered application. Use it instead of ReactDOM.hydrate in conjunction with the new React DOM Server APIs. New features in React 18 don’t work without it.

    Both createRoot and hydrateRoot accept a new option called onRecoverableError in case you want to be notified when React recovers from errors during rendering or hydration for logging. By default, React will use reportError, or console.error in the older browsers.

    See docs for React DOM Client here.

    React DOM Server

    These new APIs are now exported from react-dom/server and have full support for streaming Suspense on the server:

    • renderToPipeableStream: for streaming in Node environments.
    • renderToReadableStream: for modern edge runtime environments, such as Deno and Cloudflare workers.

    The existing renderToString method keeps working but is discouraged.

    See docs for React DOM Server here.

    New Strict Mode Behaviors

    In the future, we’d like to add a feature that allows React to add and remove sections of the UI while preserving state. For example, when a user tabs away from a screen and back, React should be able to immediately show the previous screen. To do this, React would unmount and remount trees using the same component state as before.

    This feature will give React apps better performance out-of-the-box, but requires components to be resilient to effects being mounted and destroyed multiple times. Most effects will work without any changes, but some effects assume they are only mounted or destroyed once.

    To help surface these issues, React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.

    Before this change, React would mount the component and create the effects:

    * React mounts the component.
      * Layout effects are created.
      * Effects are created.

    With Strict Mode in React 18, React will simulate unmounting and remounting the component in development mode:

    * React mounts the component.
      * Layout effects are created.
      * Effects are created.
    * React simulates unmounting the component.
      * Layout effects are destroyed.
      * Effects are destroyed.
    * React simulates mounting the component with the previous state.
      * Layout effects are created.
      * Effects are created.

    See docs for ensuring reusable state here.

    New Hooks

    useId

    useId is a new hook for generating unique IDs on both the client and server, while avoiding hydration mismatches. It is primarily useful for component libraries integrating with accessibility APIs that require unique IDs. This solves an issue that already exists in React 17 and below, but it’s even more important in React 18 because of how the new streaming server renderer delivers HTML out-of-order. See docs here.

    Note

    useId is not for generating keys in a list. Keys should be generated from your data.

    useTransition

    useTransition and startTransition let you mark some state updates as not urgent. Other state updates are considered urgent by default. React will allow urgent state updates (for example, updating a text input) to interrupt non-urgent state updates (for example, rendering a list of search results). See docs here

    useDeferredValue

    useDeferredValue lets you defer re-rendering a non-urgent part of the tree. It is similar to debouncing, but has a few advantages compared to it. There is no fixed time delay, so React will attempt the deferred render right after the first render is reflected on the screen. The deferred render is interruptible and doesn’t block user input. See docs here.

    useSyncExternalStore

    useSyncExternalStore is a new hook that allows external stores to support concurrent reads by forcing updates to the store to be synchronous. It removes the need for useEffect when implementing subscriptions to external data sources, and is recommended for any library that integrates with state external to React. See docs here.

    Note

    useSyncExternalStore is intended to be used by libraries, not application code.

    useInsertionEffect

    useInsertionEffect is a new hook that allows CSS-in-JS libraries to address performance issues of injecting styles in render. Unless you’ve already built a CSS-in-JS library we don’t expect you to ever use this. This hook will run after the DOM is mutated, but before layout effects read the new layout. This solves an issue that already exists in React 17 and below, but is even more important in React 18 because React yields to the browser during concurrent rendering, giving it a chance to recalculate layout. See docs here.

    Note

    useInsertionEffect is intended to be used by libraries, not application code.

    How to Upgrade

    See How to Upgrade to React 18 for step-by-step instructions and a full list of breaking and notable changes.

    Changelog

    React

    • 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)
    • Add useId for generating unique IDs. (#17322, #18576, #22644, #22672, #21260 by @acdlite, @lunaruan, and @sebmarkbage)
    • Add useSyncExternalStore to help external store libraries integrate with React. (#15022, #18000, #18771, #22211, #22292, #22239, #22347, #23150 by @acdlite, @bvaughn, and @drarmstr)
    • Add startTransition as a version of useTransition without pending feedback. (#19696 by @rickhanlonii)
    • Add useInsertionEffect for CSS-in-JS libraries. (#21913 by @rickhanlonii)
    • Make Suspense remount layout effects when content reappears. (#19322, #19374, #19523, #20625, #21079 by @acdlite, @bvaughn, and @lunaruan)
    • Make <StrictMode> re-run effects to check for restorable state. (#19523 , #21418 by @bvaughn and @lunaruan)
    • Assume Symbols are always available. (#23348 by @sebmarkbage)
    • Remove object-assign polyfill. (#23351 by @sebmarkbage)
    • Remove unsupported unstable_changedBits API. (#20953 by @acdlite)
    • Allow components to render undefined. (#21869 by @rickhanlonii)
    • Flush useEffect resulting from discrete events like clicks synchronously. (#21150 by @acdlite)
    • Suspense fallback={undefined} now behaves the same as null and isn’t ignored. (#21854 by @rickhanlonii)
    • Consider all lazy() resolving to the same component equivalent. (#20357 by @sebmarkbage)
    • Don’t patch console during first render. (#22308 by @lunaruan)
    • Improve memory usage. (#21039 by @bgirard)
    • Improve messages if string coercion throws (Temporal.*, Symbol, etc.) (#22064 by @justingrant)
    • Use setImmediate when available over MessageChannel. (#20834 by @gaearon)
    • Fix context failing to propagate inside suspended trees. (#23095 by @gaearon)
    • Fix useReducer observing incorrect props by removing the eager bailout mechanism. (#22445 by @josephsavona)
    • Fix setState being ignored in Safari when appending iframes. (#23111 by @gaearon)
    • Fix a crash when rendering ZonedDateTime in the tree. (#20617 by @dimaqq)
    • Fix a crash when document is set to null in tests. (#22695 by @SimenB)
    • Fix onLoad not triggering when concurrent features are on. (#23316 by @gnoff)
    • Fix a warning when a selector returns NaN. (#23333 by @hachibeeDI)
    • Fix a crash when document is set to null in tests. (#22695 by @SimenB)
    • Fix the generated license header. (#23004 by @vitaliemiron)
    • Add package.json as one of the entry points. (#22954 by @Jack)
    • Allow suspending outside a Suspense boundary. (#23267 by @acdlite)
    • Log a recoverable error whenever hydration fails. (#23319 by @acdlite)

    React DOM

    • Add createRoot and hydrateRoot. (#10239, #11225, #12117, #13732, #15502, #15532, #17035, #17165, #20669, #20748, #20888, #21072, #21417, #21652, #21687, #23207, #23385 by @acdlite, @bvaughn, @gaearon, @lunaruan, @rickhanlonii, @trueadm, and @sebmarkbage)
    • Add selective hydration. (#14717, #14884, #16725, #16880, #17004, #22416, #22629, #22448, #22856, #23176 by @acdlite, @gaearon, @salazarm, and @sebmarkbage)
    • Add aria-description to the list of known ARIA attributes. (#22142 by @mahyareb)
    • Add onResize event to video elements. (#21973 by @rileyjshaw)
    • Add imageSizes and imageSrcSet to known props. (#22550 by @eps1lon)
    • Allow non-string <option> children if value is provided. (#21431 by @sebmarkbage)
    • Fix aspectRatio style not being applied. (#21100 by @gaearon)
    • Warn if renderSubtreeIntoContainer is called. (#23355 by @acdlite)

    React DOM Server

    • Add the new streaming renderer. (#14144, #20970, #21056, #21255, #21200, #21257, #21276, #22443, #22450, #23247, #24025, #24030 by @sebmarkbage)
    • Fix context providers in SSR when handling multiple requests. (#23171 by @frandiox)
    • Revert to client render on text mismatch. (#23354 by @acdlite)
    • Deprecate renderToNodeStream. (#23359 by @sebmarkbage)
    • Fix a spurious error log in the new server renderer. (#24043 by @eps1lon)
    • Fix a bug in the new server renderer. (#22617 by @shuding)
    • Ignore function and symbol values inside custom elements on the server. (#21157 by @sebmarkbage)

    React DOM Test Utils

    • Throw when act is used in production. (#21686 by @acdlite)
    • Support disabling spurious act warnings with global.IS_REACT_ACT_ENVIRONMENT. (#22561 by @acdlite)
    • Expand act warning to cover all APIs that might schedule React work. (#22607 by @acdlite)
    • Make act batch updates. (#21797 by @acdlite)
    • Remove warning for dangling passive effects. (#22609 by @acdlite)

    React Refresh

    • Track late-mounted roots in Fast Refresh. (#22740 by @anc95)
    • Add exports field to package.json. (#23087 by @otakustay)

    Server Components (Experimental)

    • Add Server Context support. (#23244 by @salazarm)
    • Add lazy support. (#24068 by @gnoff)
    • Update webpack plugin for webpack 5 (#22739 by @michenly)
    • Fix a mistake in the Node loader. (#22537 by @btea)
    • Use globalThis instead of window for edge environments. (#22777 by @huozhi)
  • React Blog reactjs.org framework javascript react technology web-dev web-development 2022-03-08 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. As we shared in the release post, React 18 introduces features powered by our new concurrent renderer, with a gradual adoption strategy for existing applications. In this post, we will guide you...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    As we shared in the release post, React 18 introduces features powered by our new concurrent renderer, with a gradual adoption strategy for existing applications. In this post, we will guide you through the steps for upgrading to React 18.

    Please report any issues you encounter while upgrading to React 18.

    Note for React Native users: React 18 will ship in a future version of React Native. This is because React 18 relies on the New React Native Architecture to benefit from the new capabilities presented in this blogpost. For more information, see the React Conf keynote here.

    Installing

    To install the latest version of React:

    npm install react react-dom

    Or if you’re using yarn:

    yarn add react react-dom

    Updates to Client Rendering APIs

    When you first install React 18, you will see a warning in the console:

    ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it’s running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

    React 18 introduces a new root API which provides better ergonomics for managing roots. The new root API also enables the new concurrent renderer, which allows you to opt-into concurrent features.

    // Before
    import { render } from 'react-dom';
    const container = document.getElementById('app');
    render(<App tab="home" />, container);
    
    // After
    import { createRoot } from 'react-dom/client';
    const container = document.getElementById('app');
    const root = createRoot(container); // createRoot(container!) if you use TypeScript
    root.render(<App tab="home" />);

    We’ve also changed unmountComponentAtNode to root.unmount:

    // Before
    unmountComponentAtNode(container);
    
    // After
    root.unmount();

    We’ve also removed the callback from render, since it usually does not have the expected result when using Suspense:

    // Before
    const container = document.getElementById('app');
    render(<App tab="home" />, container, () => {
      console.log('rendered');
    });
    
    // After
    function AppWithCallbackAfterRender() {
      useEffect(() => {
        console.log('rendered');
      });
    
      return <App tab="home" />
    }
    
    const container = document.getElementById('app');
    const root = createRoot(container);
    root.render(<AppWithCallbackAfterRender />);

    Note:

    There is no one-to-one replacement for the old render callback API — it depends on your use case. See the working group post for Replacing render with createRoot for more information.

    Finally, if your app uses server-side rendering with hydration, upgrade hydrate to hydrateRoot:

    // Before
    import { hydrate } from 'react-dom';
    const container = document.getElementById('app');
    hydrate(<App tab="home" />, container);
    
    // After
    import { hydrateRoot } from 'react-dom/client';
    const container = document.getElementById('app');
    const root = hydrateRoot(container, <App tab="home" />);
    // Unlike with createRoot, you don't need a separate root.render() call here.

    For more information, see the working group discussion here.

    Note

    If your app doesn’t work after upgrading, check whether it’s wrapped in <StrictMode>. Strict Mode has gotten stricter in React 18, and not all your components may be resilient to the new checks it adds in development mode. If removing Strict Mode fixes your app, you can remove it during the upgrade, and then add it back (either at the top or for a part of the tree) after you fix the issues that it’s pointing out.

    Updates to Server Rendering APIs

    In this release, we’re revamping our react-dom/server APIs to fully support Suspense on the server and Streaming SSR. As part of these changes, we’re deprecating the old Node streaming API, which does not support incremental Suspense streaming on the server.

    Using this API will now warn:

    • renderToNodeStream: Deprecated ⛔️️

    Instead, for streaming in Node environments, use:

    • renderToPipeableStream: New ✨

    We’re also introducing a new API to support streaming SSR with Suspense for modern edge runtime environments, such as Deno and Cloudflare workers:

    • renderToReadableStream: New ✨

    The following APIs will continue working, but with limited support for Suspense:

    • renderToString: Limited ⚠️
    • renderToStaticMarkup: Limited ⚠️

    Finally, this API will continue to work for rendering e-mails:

    • renderToStaticNodeStream

    For more information on the changes to server rendering APIs, see the working group post on Upgrading to React 18 on the server, a deep dive on the new Suspense SSR Architecture, and Shaundai Person’s talk on Streaming Server Rendering with Suspense at React Conf 2021.

    Updates to TypeScript definitions

    If your project uses TypeScript, you will need to update your @types/react and @types/react-dom dependencies to the latest versions. The new types are safer and catch issues that used to be ignored by the type checker. The most notable change is that the children prop now needs to be listed explicitly when defining props, for example:

    interface MyButtonProps {
      color: string;
      children?: React.ReactNode;}

    See the React 18 typings pull request for a full list of type-only changes. It links to example fixes in library types so you can see how to adjust your code. You can use the automated migration script to help port your application code to the new and safer typings faster.

    If you find a bug in the typings, please file an issue in the DefinitelyTyped repo.

    Automatic Batching

    React 18 adds out-of-the-box performance improvements by doing more batching by default. Batching is when React groups multiple state updates into a single re-render for better performance. Before React 18, we only batched updates inside React event handlers. Updates inside of promises, setTimeout, native event handlers, or any other event were not batched in React by default:

    // Before React 18 only React events were batched
    
    function handleClick() {
      setCount(c => c + 1);
      setFlag(f => !f);
      // React will only re-render once at the end (that's batching!)
    }
    
    setTimeout(() => {
      setCount(c => c + 1);
      setFlag(f => !f);
      // React will render twice, once for each state update (no batching)
    }, 1000);

    Starting in React 18 with createRoot, all updates will be automatically batched, no matter where they originate from. This means that updates inside of timeouts, promises, native event handlers or any other event will batch the same way as updates inside of React events:

    // After React 18 updates inside of timeouts, promises,
    // native event handlers or any other event are batched.
    
    function handleClick() {
      setCount(c => c + 1);
      setFlag(f => !f);
      // React will only re-render once at the end (that's batching!)
    }
    
    setTimeout(() => {
      setCount(c => c + 1);
      setFlag(f => !f);
      // React will only re-render once at the end (that's batching!)
    }, 1000);

    This is a breaking change, but we expect this to result in less work rendering, and therefore better performance in your applications. To opt-out of automatic batching, you can use flushSync:

    import { flushSync } from 'react-dom';
    
    function handleClick() {
      flushSync(() => {
        setCounter(c => c + 1);
      });
      // React has updated the DOM by now
      flushSync(() => {
        setFlag(f => !f);
      });
      // React has updated the DOM by now
    }

    For more information, see the Automatic batching deep dive.

    New APIs for Libraries

    In the React 18 Working Group we worked with library maintainers to create new APIs needed to support concurrent rendering for use cases specific to their use case in areas like styles, and external stores. To support React 18, some libraries may need to switch to one of the following APIs:

    • useSyncExternalStore is a new hook that allows external stores to support concurrent reads by forcing updates to the store to be synchronous. This new API is recommended for any library that integrates with state external to React. For more information, see the useSyncExternalStore overview post and useSyncExternalStore API details.
    • useInsertionEffect is a new hook that allows CSS-in-JS libraries to address performance issues of injecting styles in render. Unless you’ve already built a CSS-in-JS library we don’t expect you to ever use this. This hook will run after the DOM is mutated, but before layout effects read the new layout. This solves an issue that already exists in React 17 and below, but is even more important in React 18 because React yields to the browser during concurrent rendering, giving it a chance to recalculate layout. For more information, see the Library Upgrade Guide for <style>.

    React 18 also introduces new APIs for concurrent rendering such as startTransition, useDeferredValue and useId, which we share more about in the release post.

    Updates to Strict Mode

    In the future, we’d like to add a feature that allows React to add and remove sections of the UI while preserving state. For example, when a user tabs away from a screen and back, React should be able to immediately show the previous screen. To do this, React would unmount and remount trees using the same component state as before.

    This feature will give React better performance out-of-the-box, but requires components to be resilient to effects being mounted and destroyed multiple times. Most effects will work without any changes, but some effects assume they are only mounted or destroyed once.

    To help surface these issues, React 18 introduces a new development-only check to Strict Mode. This new check will automatically unmount and remount every component, whenever a component mounts for the first time, restoring the previous state on the second mount.

    Before this change, React would mount the component and create the effects:

    * React mounts the component.
        * Layout effects are created.
        * Effect effects are created.

    With Strict Mode in React 18, React will simulate unmounting and remounting the component in development mode:

    * React mounts the component.
        * Layout effects are created.
        * Effect effects are created.
    * React simulates unmounting the component.
        * Layout effects are destroyed.
        * Effects are destroyed.
    * React simulates mounting the component with the previous state.
        * Layout effect setup code runs
        * Effect setup code runs

    For more information, see the Working Group posts for Adding Reusable State to StrictMode and How to support Reusable State in Effects.

    Configuring Your Testing Environment

    When you first update your tests to use createRoot, you may see this warning in your test console:

    The current testing environment is not configured to support act(…)

    To fix this, set globalThis.IS_REACT_ACT_ENVIRONMENT to true before running your test:

    // In your test setup file
    globalThis.IS_REACT_ACT_ENVIRONMENT = true;

    The purpose of the flag is to tell React that it’s running in a unit test-like environment. React will log helpful warnings if you forget to wrap an update with act.

    You can also set the flag to false to tell React that act isn’t needed. This can be useful for end-to-end tests that simulate a full browser environment.

    Eventually, we expect testing libraries will configure this for you automatically. For example, the next version of React Testing Library has built-in support for React 18 without any additional configuration.

    More background on the act testing API and related changes is available in the working group.

    Dropping Support for Internet Explorer

    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.

    Deprecations

    • react-dom: ReactDOM.render has been deprecated. Using it will warn and run your app in React 17 mode.
    • react-dom: ReactDOM.hydrate has been deprecated. Using it will warn and run your app in React 17 mode.
    • react-dom: ReactDOM.unmountComponentAtNode has been deprecated.
    • react-dom: ReactDOM.renderSubtreeIntoContainer has been deprecated.
    • react-dom/server: ReactDOMServer.renderToNodeStream has been deprecated.

    Other Breaking Changes

    • Consistent useEffect timing: React now always synchronously flushes effect functions if the update was triggered during a discrete user input event such as a click or a keydown event. Previously, the behavior wasn’t always predictable or consistent.
    • Stricter hydration errors: Hydration mismatches due to missing or extra text content are now treated like errors instead of warnings. React will no longer attempt to “patch up” individual nodes by inserting or deleting a node on the client in an attempt to match the server markup, and will revert to client rendering up to the closest <Suspense> boundary in the tree. This ensures the hydrated tree is consistent and avoids potential privacy and security holes that can be caused by hydration mismatches.
    • Suspense trees are always consistent: If a component suspends before it’s fully added to the tree, React will not add it to the tree in an incomplete state or fire its effects. Instead, React will throw away the new tree completely, wait for the asynchronous operation to finish, and then retry rendering again from scratch. React will render the retry attempt concurrently, and without blocking the browser.
    • Layout Effects with Suspense: When a tree re-suspends and reverts to a fallback, React will now clean up layout effects, and then re-create them when the content inside the boundary is shown again. This fixes an issue which prevented component libraries from correctly measuring layout when used with Suspense.
    • New JS Environment Requirements: React now depends on modern browsers features including Promise, Symbol, and Object.assign. If you support older browsers and devices such as Internet Explorer which do not provide modern browser features natively or have non-compliant implementations, consider including a global polyfill in your bundled application.

    Other Notable Changes

    React

    • Components can now render undefined: React no longer warns if you return undefined from a component. This makes the allowed component return values consistent with values that are allowed in the middle of a component tree. We suggest to use a linter to prevent mistakes like forgetting a return statement before JSX.
    • In tests, act warnings are now opt-in: If you’re running end-to-end tests, the act warnings are unnecessary. We’ve introduced an opt-in mechanism so you can enable them only for unit tests where they are useful and beneficial.
    • No warning about setState on unmounted components: Previously, React warned about memory leaks when you call setState on an unmounted component. This warning was added for subscriptions, but people primarily run into it in scenarios where setting state is fine, and workarounds make the code worse. We’ve removed this warning.
    • No suppression of console logs: When you use Strict Mode, React renders each component twice to help you find unexpected side effects. In React 17, we’ve suppressed console logs for one of the two renders to make the logs easier to read. In response to community feedback about this being confusing, we’ve removed the suppression. Instead, if you have React DevTools installed, the second log’s renders will be displayed in grey, and there will be an option (off by default) to suppress them completely.
    • Improved memory usage: React now cleans up more internal fields on unmount, making the impact from unfixed memory leaks that may exist in your application code less severe.

    React DOM Server

    • renderToString: Will no longer error when suspending on the server. Instead, it will emit the fallback HTML for the closest <Suspense> boundary and then retry rendering the same content on the client. It is still recommended that you switch to a streaming API like renderToPipeableStream or renderToReadableStream instead.
    • renderToStaticMarkup: Will no longer error when suspending on the server. Instead, it will emit the fallback HTML for the closest <Suspense> boundary.

    Changelog

    You can view the full changelog here.

  • React Blog reactjs.org framework javascript react technology web-dev web-development 2021-12-17 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. Last week we hosted our 6th React Conf. In previous years, we’ve used the React Conf stage to deliver industry changing announcements such as React Native and React Hooks. This year, we shared our...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    Last week we hosted our 6th React Conf. In previous years, we’ve used the React Conf stage to deliver industry changing announcements such as React Native and React Hooks. This year, we shared our multi-platform vision for React, starting with the release of React 18 and gradual adoption of concurrent features.

    This was the first time React Conf was hosted online, and it was streamed for free, translated to 8 different languages. Participants from all over the world joined our conference Discord and the replay event for accessibility in all timezones. Over 50,000 people registered, with over 60,000 views of 19 talks, and 5,000 participants in Discord across both events.

    All the talks are available to stream online.

    Here’s a summary of what was shared on stage:

    React 18 and concurrent features

    In the keynote, we shared our vision for the future of React starting with React 18.

    React 18 adds the long-awaited concurrent renderer and updates to Suspense without any major breaking changes. Apps can upgrade to React 18 and begin gradually adopting concurrent features with the amount of effort on par with any other major release.

    This means there is no concurrent mode, only concurrent features.

    In the keynote, we also shared our vision for Suspense, Server Components, new React working groups, and our long-term many-platform vision for React Native.

    Watch the full keynote from Andrew Clark, Juan Tejada, Lauren Tan, and Rick Hanlon here:

    React 18 for Application Developers

    In the keynote, we also announced that the React 18 RC is available to try now. Pending further feedback, this is the exact version of React that we will publish to stable early next year.

    To try the React 18 RC, upgrade your dependencies:

    npm install react@rc react-dom@rc

    and switch to the new createRoot API:

    // before
    const container = document.getElementById('root');
    ReactDOM.render(<App />, container);
    
    // after
    const container = document.getElementById('root');
    const root = ReactDOM.createRoot(container);
    root.render(<App/>);

    For a demo of upgrading to React 18, see Shruti Kapoor’s talk here:

    Streaming Server Rendering with Suspense

    React 18 also includes improvements to server-side rendering performance using Suspense.

    Streaming server rendering lets you generate HTML from React components on the server, and stream that HTML to your users. In React 18, you can use Suspense to break down your app into smaller independent units which can be streamed independently of each other without blocking the rest of the app. This means users will see your content sooner and be able to start interacting with it much faster.

    For a deep dive, see Shaundai Person’s talk here:

    The first React working group

    For React 18, we created our first Working Group to collaborate with a panel of experts, developers, library maintainers, and educators. Together we worked to create our gradual adoption strategy and refine new APIs such as useId, useSyncExternalStore, and useInsertionEffect.

    For an overview of this work, see Aakansha’ Doshi’s talk:

    React Developer Tooling

    To support the new features in this release, we also announced the newly formed React DevTools team and a new Timeline Profiler to help developers debug their React apps.

    For more information and a demo of new DevTools features, see Brian Vaughn’s talk:

    React without memo

    Looking further into the future, Xuan Huang (黄玄) shared an update from our React Labs research into an auto-memoizing compiler. Check out this talk for more information and a demo of the compiler prototype:

    React docs keynote

    Rachel Nabors kicked off a section of talks about learning and designing with React with a keynote about our investment in React’s new docs:

    And more…

    We also heard talks on learning and designing with React:

    • Debbie O’Brien: Things I learnt from the new React docs.
    • Sarah Rainsberger: Learning in the Browser.
    • Linton Ye: The ROI of Designing with React.
    • Delba de Oliveira: Interactive playgrounds with React.

    Talks from the Relay, React Native, and PyTorch teams:

    • Robert Balicki: Re-introducing Relay.
    • Eric Rozell and Steven Moyes: React Native Desktop.
    • Roman Rädle: On-device Machine Learning for React Native

    And talks from the community on accessibility, tooling, and Server Components:

    • Daishi Kato: React 18 for External Store Libraries.
    • Diego Haz: Building Accessible Components in React 18.
    • Tafu Nakazaki: Accessible Japanese Form Components with React.
    • Lyle Troxell: UI tools for artists.
    • Helen Lin: Hydrogen + React 18.

    Thank you

    This was our first year planning a conference ourselves, and we have a lot of people to thank.

    First, thanks to all of our speakers Aakansha Doshi, Andrew Clark, Brian Vaughn, Daishi Kato, Debbie O’Brien, Delba de Oliveira, Diego Haz, Eric Rozell, Helen Lin, Juan Tejada, Lauren Tan, Linton Ye, Lyle Troxell, Rachel Nabors, Rick Hanlon, Robert Balicki, Roman Rädle, Sarah Rainsberger, Shaundai Person, Shruti Kapoor, Steven Moyes, Tafu Nakazaki, and Xuan Huang (黄玄).

    Thanks to everyone who helped provide feedback on talks including Andrew Clark, Dan Abramov, Dave McCabe, Eli White, Joe Savona, Lauren Tan, Rachel Nabors, and Tim Yung.

    Thanks to Lauren Tan for setting up the conference Discord and serving as our Discord admin.

    Thanks to Seth Webster for feedback on overall direction and making sure we were focused on diversity and inclusion.

    Thanks to Rachel Nabors for spearheading our moderation effort, and Aisha Blake for creating our moderation guide, leading our moderation team, training the translators and moderators, and helping to moderate both events.

    Thanks to our moderators Jesslyn Tannady, Suzie Grange, Becca Bailey, Luna Wei, Joe Previte, Nicola Corti, Gijs Weterings, Claudio Procida, Julia Neumann, Mengdi Chen, Jean Zhang, Ricky Li, and Xuan Huang (黄玄).

    Thanks to Manjula Dube, Sahil Mhapsekar, and Vihang Patel from React India, and Jasmine Xie, QiChang Li, and YanLun Li from React China for helping moderate our replay event and keep it engaging for the community.

    Thanks to Vercel for publishing their Virtual Event Starter Kit, which the conference website was built on, and to Lee Robinson and Delba de Oliveira for sharing their experience running Next.js Conf.

    Thanks to Leah Silber for sharing her experience running conferences, learnings from running RustConf, and for her book Event Driven and the advice it contains for running conferences.

    Thanks to Kevin Lewis and Rachel Nabors for sharing their experience running Women of React Conf.

    Thanks to Aakansha Doshi, Laurie Barth, Michael Chan, and Shaundai Person for their advice and ideas throughout planning.

    Thanks to Dan Lebowitz for help designing and building the conference website and tickets.

    Thanks to Laura Podolak Waddell, Desmond Osei-Acheampong, Mark Rossi, Josh Toberman and others on the Facebook Video Productions team for recording the videos for the Keynote and Meta employee talks.

    Thanks to our partner HitPlay for helping to organize the conference, editing all the videos in the stream, translating all the talks, and moderating the Discord in multiple languages.

    Finally, thanks to all of our participants for making this a great React Conf!

  • React Blog reactjs.org framework javascript react technology web-dev web-development 2021-06-08 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. Update Nov. 15th, 2021 React 18 is now in beta. More information about the status of the release is available in the React 18 Working Group post. The React team is excited to share a few updates:...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    Update Nov. 15th, 2021

    React 18 is now in beta. More information about the status of the release is available in the React 18 Working Group post.

    The React team is excited to share a few updates:

    1. We’ve started work on the React 18 release, which will be our next major version.
    2. We’ve created a Working Group to prepare the community for gradual adoption of new features in React 18.
    3. We’ve published a React 18 Alpha so that library authors can try it and provide feedback.

    These updates are primarily aimed at maintainers of third-party libraries. If you’re learning, teaching, or using React to build user-facing applications, you can safely ignore this post. But you are welcome to follow the discussions in the React 18 Working Group if you’re curious!

    What’s coming in React 18

    When it’s released, React 18 will include out-of-the-box improvements (like automatic batching), new APIs (like startTransition), and a new streaming server renderer with built-in support for React.lazy.

    These features are possible thanks to a new opt-in mechanism we’re adding in React 18. It’s called “concurrent rendering” and it lets React prepare multiple versions of the UI at the same time. This change is mostly behind-the-scenes, but it unlocks new possibilities to improve both real and perceived performance of your app.

    If you’ve been following our research into the future of React (we don’t expect you to!), you might have heard of something called “concurrent mode” or that it might break your app. In response to this feedback from the community, we’ve redesigned the upgrade strategy for gradual adoption. Instead of an all-or-nothing “mode”, concurrent rendering will only be enabled for updates triggered by one of the new features. In practice, this means you will be able to adopt React 18 without rewrites and try the new features at your own pace.

    A gradual adoption strategy

    Since concurrency in React 18 is opt-in, there are no significant out-of-the-box breaking changes to component behavior. You can upgrade to React 18 with minimal or no changes to your application code, with a level of effort comparable to a typical major React release. Based on our experience converting several apps to React 18, we expect that many users will be able to upgrade within a single afternoon.

    We successfully shipped concurrent features to tens of thousands of components at Facebook, and in our experience, we’ve found that most React components “just work” without additional changes. We’re committed to making sure this is a smooth upgrade for the entire community, so today we’re announcing the React 18 Working Group.

    Working with the community

    We’re trying something new for this release: We’ve invited a panel of experts, developers, library authors, and educators from across the React community to participate in our React 18 Working Group to provide feedback, ask questions, and collaborate on the release. We couldn’t invite everyone we wanted to this initial, small group, but if this experiment works out, we hope there will be more in the future!

    The goal of the React 18 Working Group is to prepare the ecosystem for a smooth, gradual adoption of React 18 by existing applications and libraries. The Working Group is hosted on GitHub Discussions and is available for the public to read. Members of the working group can leave feedback, ask questions, and share ideas. The core team will also use the discussions repo to share our research findings. As the stable release gets closer, any important information will also be posted on this blog.

    For more information on upgrading to React 18, or additional resources about the release, see the React 18 announcement post.

    Accessing the React 18 Working Group

    Everyone can read the discussions in the React 18 Working Group repo.

    Because we expect an initial surge of interest in the Working Group, only invited members will be allowed to create or comment on threads. However, the threads are fully visible to the public, so everyone has access to the same information. We believe this is a good compromise between creating a productive environment for working group members, while maintaining transparency with the wider community.

    As always, you can submit bug reports, questions, and general feedback to our issue tracker.

    How to try React 18 Alpha today

    New alphas are regularly published to npm using the @alpha tag. These releases are built using the most recent commit to our main repo. When a feature or bugfix is merged, it will appear in an alpha the following weekday.

    There may be significant behavioral or API changes between alpha releases. Please remember that alpha releases are not recommended for user-facing, production applications.

    Projected React 18 release timeline

    We don’t have a specific release date scheduled, but we expect it will take several months of feedback and iteration before React 18 is ready for most production applications.

    • Library Alpha: Available today
    • Public Beta: At least several months
    • Release Candidate (RC): At least several weeks after Beta
    • General Availability: At least several weeks after RC

    More details about our projected release timeline are available in the Working Group. We’ll post updates on this blog when we’re closer to a public release.

  • React Blog reactjs.org framework javascript react technology web-dev web-development 2020-12-21 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. 2020 has been a long year. As it comes to an end we wanted to share a special Holiday Update on our research into zero-bundle-size React Server Components. To introduce React Server Components, we...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    2020 has been a long year. As it comes to an end we wanted to share a special Holiday Update on our research into zero-bundle-size React Server Components.

    To introduce React Server Components, we have prepared a talk and a demo. If you want, you can check them out during the holidays, or later when work picks back up in the new year.


    React Server Components are still in research and development. We are sharing this work in the spirit of transparency and to get initial feedback from the React community. There will be plenty of time for that, so don’t feel like you have to catch up right now!

    If you want to check them out, we recommend to go in the following order:

    1. Watch the talk to learn about React Server Components and see the demo.
    2. Clone the demo to play with React Server Components on your computer.
    3. Read the RFC (with FAQ at the end) for a deeper technical breakdown and to provide feedback.

    We are excited to hear from you on the RFC or in replies to the @reactjs Twitter handle. Happy holidays, stay safe, and see you next year!

  • React Blog reactjs.org framework javascript react technology web-dev web-development 2020-10-20 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. Today, we are releasing React 17! We’ve written at length about the role of the React 17 release and the changes it contains in the React 17 RC blog post. This post is a brief summary of it, so if...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    Today, we are releasing React 17! We’ve written at length about the role of the React 17 release and the changes it contains in the React 17 RC blog post. This post is a brief summary of it, so if you’ve already read the RC post, you can skip this one.

    No New Features

    The React 17 release is unusual because it doesn’t add any new developer-facing features. Instead, this release is primarily focused on making it easier to upgrade React itself.

    In particular, React 17 is a “stepping stone” release that makes it safer to embed a tree managed by one version of React inside a tree managed by a different version of React.

    It also makes it easier to embed React into apps built with other technologies.

    Gradual Upgrades

    React 17 enables gradual React upgrades. When you upgrade from React 15 to 16 (or, this time, from React 16 to 17), you would usually upgrade your whole app at once. This works well for many apps. But it can get increasingly challenging if the codebase was written more than a few years ago and isn’t actively maintained. And while it’s possible to use two versions of React on the page, until React 17 this has been fragile and caused problems with events.

    We’re fixing many of those problems with React 17. This means that when React 18 and the next future versions come out, you will now have more options. The first option will be to upgrade your whole app at once, like you might have done before. But you will also have an option to upgrade your app piece by piece. For example, you might decide to migrate most of your app to React 18, but keep some lazy-loaded dialog or a subroute on React 17.

    This doesn’t mean you have to do gradual upgrades. For most apps, upgrading all at once is still the best solution. Loading two versions of React — even if one of them is loaded lazily on demand — is still not ideal. However, for larger apps that aren’t actively maintained, this option makes sense to consider, and React 17 lets those apps not get left behind.

    We’ve prepared an example repository demonstrating how to lazy-load an older version of React if necessary. This demo uses Create React App, but it should be possible to follow a similar approach with any other tool. We welcome demos using other tooling as pull requests.

    Note

    We’ve postponed other changes until after React 17. The goal of this release is to enable gradual upgrades. If upgrading to React 17 were too difficult, it would defeat its purpose.

    Changes to Event Delegation

    To enable gradual updates, we’ve needed to make some changes to the React event system. React 17 is a major release because these changes are potentially breaking. You can check out our versioning FAQ to learn more about our commitment to stability.

    In React 17, React will no longer attach event handlers at the document level under the hood. Instead, it will attach them to the root DOM container into which your React tree is rendered:

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

    In React 16 and earlier, React would do document.addEventListener() for most events. React 17 will call rootNode.addEventListener() under the hood instead.

    A diagram showing how React 17 attaches events to the roots rather than to the document

    We’ve confirmed that numerous problems reported over the years on our issue tracker related to integrating React with non-React code have been fixed by the new behavior.

    If you run into issues with this change, here’s a common way to resolve them.

    Other Breaking Changes

    The React 17 RC blog post describes the rest of the breaking changes in React 17.

    We’ve only had to change fewer than twenty components out of 100,000+ in the Facebook product code to work with these changes, so we expect that most apps can upgrade to React 17 without too much trouble. Please tell us if you run into problems.

    New JSX Transform

    React 17 supports the new JSX transform. We’ve also backported support for it to React 16.14.0, React 15.7.0, and 0.14.10. Note that it is completely opt-in, and you don’t have to use it. The classic JSX transform will keep working, and there are no plans to stop supporting it.

    React Native

    React Native has a separate release schedule. We landed the support for React 17 in React Native 0.64. As always, you can track the release discussions on the React Native Community releases issue tracker.

    Installation

    To install React 17 with npm, run:

    npm install react@17.0.0 react-dom@17.0.0

    To install React 17 with Yarn, run:

    yarn add react@17.0.0 react-dom@17.0.0

    We also provide UMD builds of React via a CDN:

    <script crossorigin src="https://unpkg.com/react@17.0.0/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17.0.0/umd/react-dom.production.min.js"></script>

    Refer to the documentation for detailed installation instructions.

    Changelog

    React

    • Add react/jsx-runtime and react/jsx-dev-runtime for the new JSX transform. (@lunaruan in #18299)
    • Build component stacks from native error frames. (@sebmarkbage in #18561)
    • Allow to specify displayName on context for improved stacks. (@eps1lon in #18224)
    • Prevent 'use strict' from leaking in the UMD bundles. (@koba04 in #19614)
    • Stop using fb.me for redirects. (@cylim in #19598)

    React DOM

    • Delegate events to roots instead of document. (@trueadm in #18195 and others)
    • Clean up all effects before running any next effects. (@bvaughn in #17947)
    • Run useEffect cleanup functions asynchronously. (@bvaughn in #17925)
    • Use browser focusin and focusout for onFocus and onBlur. (@trueadm in #19186)
    • Make all Capture events use the browser capture phase. (@trueadm in #19221)
    • Don’t emulate bubbling of the onScroll event. (@gaearon in #19464)
    • Throw if forwardRef or memo component returns undefined. (@gaearon in #19550)
    • Remove event pooling. (@trueadm in #18969)
    • Stop exposing internals that won’t be needed by React Native Web. (@necolas in #18483)
    • Attach all known event listeners when the root mounts. (@gaearon in #19659)
    • Disable console in the second render pass of DEV mode double render. (@sebmarkbage in #18547)
    • Deprecate the undocumented and misleading ReactTestUtils.SimulateNative API. (@gaearon in #13407)
    • Rename private field names used in the internals. (@gaearon in #18377)
    • Don’t call User Timing API in development. (@gaearon in #18417)
    • Disable console during the repeated render in Strict Mode. (@sebmarkbage in #18547)
    • In Strict Mode, double-render components without Hooks too. (@eps1lon in #18430)
    • Allow calling ReactDOM.flushSync during lifecycle methods (but warn). (@sebmarkbage in #18759)
    • Add the code property to the keyboard event objects. (@bl00mber in #18287)
    • Add the disableRemotePlayback property for video elements. (@tombrowndev in #18619)
    • Add the enterKeyHint property for input elements. (@eps1lon in #18634)
    • Warn when no value is provided to <Context.Provider>. (@charlie1404 in #19054)
    • Warn when memo or forwardRef components return undefined. (@bvaughn in #19550)
    • Improve the error message for invalid updates. (@JoviDeCroock in #18316)
    • Exclude forwardRef and memo from stack frames. (@sebmarkbage in #18559)
    • Improve the error message when switching between controlled and uncontrolled inputs. (@vcarl in #17070)
    • Keep onTouchStart, onTouchMove, and onWheel passive. (@gaearon in #19654)
    • Fix setState hanging in development inside a closed iframe. (@gaearon in #19220)
    • Fix rendering bailout for lazy components with defaultProps. (@jddxf in #18539)
    • Fix a false positive warning when dangerouslySetInnerHTML is undefined. (@eps1lon in #18676)
    • Fix Test Utils with non-standard require implementation. (@just-boris in #18632)
    • Fix onBeforeInput reporting an incorrect event.type. (@eps1lon in #19561)
    • Fix event.relatedTarget reported as undefined in Firefox. (@claytercek in #19607)
    • Fix “unspecified error” in IE11. (@hemakshis in #19664)
    • Fix rendering into a shadow root. (@Jack-Works in #15894)
    • Fix movementX/Y polyfill with capture events. (@gaearon in #19672)
    • Use delegation for onSubmit and onReset events. (@gaearon in #19333)
    • Improve memory usage. (@trueadm in #18970)

    React DOM Server

    • Make useCallback behavior consistent with useMemo for the server renderer. (@alexmckenley in #18783)
    • Fix state leaking when a function component throws. (@pmaccart in #19212)

    React Test Renderer

    • Improve findByType error message. (@henryqdineen in #17439)

    Concurrent Mode (Experimental)

    • Revamp the priority batching heuristics. (@acdlite in #18796)
    • Add the unstable_ prefix before the experimental APIs. (@acdlite in #18825)
    • Remove unstable_discreteUpdates and unstable_flushDiscreteUpdates. (@trueadm in #18825)
    • Remove the timeoutMs argument. (@acdlite in #19703)
    • Disable <div hidden /> prerendering in favor of a different future API. (@acdlite in #18917)
    • Add unstable_expectedLoadTime to Suspense for CPU-bound trees. (@acdlite in #19936)
    • Add an experimental unstable_useOpaqueIdentifier Hook. (@lunaruan in #17322)
    • Add an experimental unstable_startTransition API. (@rickhanlonii in #19696)
    • Using act in the test renderer no longer flushes Suspense fallbacks. (@acdlite in #18596)
    • Use global render timeout for CPU Suspense. (@sebmarkbage in #19643)
    • Clear the existing root content before mounting. (@bvaughn in #18730)
    • Fix a bug with error boundaries. (@acdlite in #18265)
    • Fix a bug causing dropped updates in a suspended tree. (@acdlite in #18384 and #18457)
    • Fix a bug causing dropped render phase updates. (@acdlite in #18537)
    • Fix a bug in SuspenseList. (@sebmarkbage in #18412)
    • Fix a bug causing Suspense fallback to show too early. (@acdlite in #18411)
    • Fix a bug with class components inside SuspenseList. (@sebmarkbage in #18448)
    • Fix a bug with inputs that may cause updates to be dropped. (@jddxf in #18515 and @acdlite in #18535)
    • Fix a bug causing Suspense fallback to get stuck. (@acdlite in #18663)
    • Don’t cut off the tail of a SuspenseList if hydrating. (@sebmarkbage in #18854)
    • Fix a bug in useMutableSource that may happen when getSnapshot changes. (@bvaughn in #18297)
    • Fix a tearing bug in useMutableSource. (@bvaughn in #18912)
    • Warn if calling setState outside of render but before commit. (@sebmarkbage in #18838)
  • React Blog reactjs.org framework javascript react technology web-dev web-development 2020-09-22 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. Although React 17 doesn’t contain new features, it will provide support for a new version of the JSX transform. In this post, we will describe what it is and how to try it. What’s a JSX Transform?...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    Although React 17 doesn’t contain new features, it will provide support for a new version of the JSX transform. In this post, we will describe what it is and how to try it.

    What’s a JSX Transform?

    Browsers don’t understand JSX out of the box, so most React users rely on a compiler like Babel or TypeScript to transform JSX code into regular JavaScript. Many preconfigured toolkits like Create React App or Next.js also include a JSX transform under the hood.

    Together with the React 17 release, we’ve wanted to make a few improvements to the JSX transform, but we didn’t want to break existing setups. This is why we worked with Babel to offer a new, rewritten version of the JSX transform for people who would like to upgrade.

    Upgrading to the new transform is completely optional, but it has a few benefits:

    • With the new transform, you can use JSX without importing React.
    • Depending on your setup, its compiled output may slightly improve the bundle size.
    • It will enable future improvements that reduce the number of concepts you need to learn React.

    This upgrade will not change the JSX syntax and is not required. The old JSX transform will keep working as usual, and there are no plans to remove the support for it.

    React 17 RC already includes support for the new transform, so go give it a try! To make it easier to adopt, we’ve also backported its support to React 16.14.0, React 15.7.0, and React 0.14.10. You can find the upgrade instructions for different tools below.

    Now let’s take a closer look at the differences between the old and the new transform.

    What’s Different in the New Transform?

    When you use JSX, the compiler transforms it into React function calls that the browser can understand. The old JSX transform turned JSX into React.createElement(...) calls.

    For example, let’s say your source code looks like this:

    import React from 'react';
    
    function App() {
      return <h1>Hello World</h1>;
    }

    Under the hood, the old JSX transform turns it into regular JavaScript:

    import React from 'react';
    
    function App() {
      return React.createElement('h1', null, 'Hello world');
    }

    Note

    Your source code doesn’t need to change in any way. We’re describing how the JSX transform turns your JSX source code into the JavaScript code a browser can understand.

    However, this is not perfect:

    • Because JSX was compiled into React.createElement, React needed to be in scope if you used JSX.
    • There are some performance improvements and simplifications that React.createElement does not allow.

    To solve these issues, React 17 introduces two new entry points to the React package that are intended to only be used by compilers like Babel and TypeScript. Instead of transforming JSX to React.createElement, the new JSX transform automatically imports special functions from those new entry points in the React package and calls them.

    Let’s say that your source code looks like this:

    function App() {
      return <h1>Hello World</h1>;
    }

    This is what the new JSX transform compiles it to:

    // Inserted by a compiler (don't import it yourself!)
    import {jsx as _jsx} from 'react/jsx-runtime';
    
    function App() {
      return _jsx('h1', { children: 'Hello world' });
    }

    Note how our original code did not need to import React to use JSX anymore! (But we would still need to import React in order to use Hooks or other exports that React provides.)

    This change is fully compatible with all of the existing JSX code, so you won’t have to change your components. If you’re curious, you can check out the technical RFC for more details about how the new transform works.

    Note

    The functions inside react/jsx-runtime and react/jsx-dev-runtime must only be used by the compiler transform. If you need to manually create elements in your code, you should keep using React.createElement. It will continue to work and is not going away.

    How to Upgrade to the New JSX Transform

    If you aren’t ready to upgrade to the new JSX transform or if you are using JSX for another library, don’t worry. The old transform will not be removed and will continue to be supported.

    If you want to upgrade, you will need two things:

    • A version of React that supports the new transform (React 17 RC and higher supports it, but we’ve also released React 16.14.0, React 15.7.0, and React 0.14.10 for people who are still on the older major versions).
    • A compatible compiler (see instructions for different tools below).

    Since the new JSX transform doesn’t require React to be in scope, we’ve also prepared an automated script that will remove the unnecessary imports from your codebase.

    Create React App

    Create React App 4.0.0+ uses the new transform for compatible React versions.

    Next.js

    Next.js v9.5.3+ uses the new transform for compatible React versions.

    Gatsby

    Gatsby v2.24.5+ uses the new transform for compatible React versions.

    Note

    If you get this Gatsby error after upgrading to React 17 RC, run npm update to fix it.

    Manual Babel Setup

    Support for the new JSX transform is available in Babel v7.9.0 and above.

    First, you’ll need to update to the latest Babel and plugin transform.

    If you are using @babel/plugin-transform-react-jsx:

    # for npm users
    npm update @babel/core @babel/plugin-transform-react-jsx
    # for yarn users
    yarn upgrade @babel/core @babel/plugin-transform-react-jsx

    If you are using @babel/preset-react:

    # for npm users
    npm update @babel/core @babel/preset-react
    # for yarn users
    yarn upgrade @babel/core @babel/preset-react

    Currently, the old transform {"runtime": "classic"} is the default option. To enable the new transform, you can pass {"runtime": "automatic"} as an option to @babel/plugin-transform-react-jsx or @babel/preset-react:

    // If you are using @babel/preset-react
    {
      "presets": [
        ["@babel/preset-react", {
          "runtime": "automatic"
        }]
      ]
    }
    // If you're using @babel/plugin-transform-react-jsx
    {
      "plugins": [
        ["@babel/plugin-transform-react-jsx", {
          "runtime": "automatic"
        }]
      ]
    }

    Starting from Babel 8, "automatic" will be the default runtime for both plugins. For more information, check out the Babel documentation for @babel/plugin-transform-react-jsx and @babel/preset-react.

    Note

    If you use JSX with a library other than React, you can use the importSource option to import from that library instead — as long as it provides the necessary entry points. Alternatively, you can keep using the classic transform which will continue to be supported.

    If you’re a library author and you are implementing the /jsx-runtime entry point for your library, keep in mind that there is a case in which even the new transform has to fall back to createElement for backwards compatibility. In that case, it will auto-import createElement directly from the root entry point specified by importSource.

    ESLint

    If you are using eslint-plugin-react, the react/jsx-uses-react and react/react-in-jsx-scope rules are no longer necessary and can be turned off or removed.

    {
      // ...
      "rules": {
        // ...
        "react/jsx-uses-react": "off",
        "react/react-in-jsx-scope": "off"
      }
    }

    TypeScript

    TypeScript supports the new JSX transform in v4.1 and up.

    Flow

    Flow supports the new JSX transform in v0.126.0 and up, by adding react.runtime=automatic to your Flow configuration options.

    Removing Unused React Imports

    Because the new JSX transform will automatically import the necessary react/jsx-runtime functions, React will no longer need to be in scope when you use JSX. This might lead to unused React imports in your code. It doesn’t hurt to keep them, but if you’d like to remove them, we recommend running a “codemod” script to remove them automatically:

    cd your_project
    npx react-codemod update-react-imports

    Note

    If you’re getting errors when running the codemod, try specifying a different JavaScript dialect when npx react-codemod update-react-imports asks you to choose one. In particular, at this moment the “JavaScript with Flow” setting supports newer syntax than the “JavaScript” setting even if you don’t use Flow. File an issue if you run into problems.

    Keep in mind that the codemod output will not always match your project’s coding style, so you might want to run Prettier after the codemod finishes for consistent formatting.

    Running this codemod will:

    • Remove all unused React imports as a result of upgrading to the new JSX transform.
    • Change all default React imports (i.e. import React from "react") to destructured named imports (ex. import { useState } from "react") which is the preferred style going into the future. This codemod will not affect the existing namespace imports (i.e. import * as React from "react") which is also a valid style. The default imports will keep working in React 17, but in the longer term we encourage moving away from them.

    For example,

    import React from 'react';
    
    function App() {
      return <h1>Hello World</h1>;
    }

    will be replaced with

    function App() {
      return <h1>Hello World</h1>;
    }

    If you use some other import from React — for example, a Hook — then the codemod will convert it to a named import.

    For example,

    import React from 'react';
    
    function App() {
      const [text, setText] = React.useState('Hello World');
      return <h1>{text}</h1>;
    }

    will be replaced with

    import { useState } from 'react';
    
    function App() {
      const [text, setText] = useState('Hello World');
      return <h1>{text}</h1>;
    }

    In addition to cleaning up unused imports, this will also help you prepare for a future major version of React (not React 17) which will support ES Modules and not have a default export.

    Thanks

    We’d like to thank Babel, TypeScript, Create React App, Next.js, Gatsby, ESLint, and Flow maintainers for their help implementing and integrating the new JSX transform. We also want to thank the React community for their feedback and discussion on the related technical RFC.

  • React Blog reactjs.org framework javascript react technology web-dev web-development 2020-08-10 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. Today, we are publishing the first Release Candidate for React 17. It has been two and a half years since the previous major release of React, which is a long time even by our standards! In this...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    Today, we are publishing the first Release Candidate for React 17. It has been two and a half years since the previous major release of React, which is a long time even by our standards! In this blog post, we will describe the role of this major release, what changes you can expect in it, and how you can try this release.

    No New Features

    The React 17 release is unusual because it doesn’t add any new developer-facing features. Instead, this release is primarily focused on making it easier to upgrade React itself.

    We’re actively working on the new React features, but they’re not a part of this release. The React 17 release is a key part of our strategy to roll them out without leaving anyone behind.

    In particular, React 17 is a “stepping stone” release that makes it safer to embed a tree managed by one version of React inside a tree managed by a different version of React.

    Gradual Upgrades

    For the past seven years, React upgrades have been “all-or-nothing”. Either you stay on an old version, or you upgrade your whole app to a new version. There was no in-between.

    This has worked out so far, but we are running into the limits of the “all-or-nothing” upgrade strategy. Some API changes, for example, deprecating the legacy context API, are impossible to do in an automated way. Even though most apps written today don’t ever use them, we still support them in React. We have to choose between supporting them in React indefinitely or leaving some apps behind on an old version of React. Both of these options aren’t great.

    So we wanted to provide another option.

    React 17 enables gradual React upgrades. When you upgrade from React 15 to 16 (or, soon, from React 16 to 17), you would usually upgrade your whole app at once. This works well for many apps. But it can get increasingly challenging if the codebase was written more than a few years ago and isn’t actively maintained. And while it’s possible to use two versions of React on the page, until React 17 this has been fragile and caused problems with events.

    We’re fixing many of those problems with React 17. This means that when React 18 and the next future versions come out, you will now have more options. The first option will be to upgrade your whole app at once, like you might have done before. But you will also have an option to upgrade your app piece by piece. For example, you might decide to migrate most of your app to React 18, but keep some lazy-loaded dialog or a subroute on React 17.

    This doesn’t mean you have to do gradual upgrades. For most apps, upgrading all at once is still the best solution. Loading two versions of React — even if one of them is loaded lazily on demand — is still not ideal. However, for larger apps that aren’t actively maintained, this option may make sense to consider, and React 17 enables those apps to not get left behind.

    To enable gradual updates, we’ve needed to make some changes to the React event system. React 17 is a major release because these changes are potentially breaking. In practice, we’ve only had to change fewer than twenty components out of 100,000+ so we expect that most apps can upgrade to React 17 without too much trouble. Tell us if you run into problems.

    Demo of Gradual Upgrades

    We’ve prepared an example repository demonstrating how to lazy-load an older version of React if necessary. This demo uses Create React App, but it should be possible to follow a similar approach with any other tool. We welcome demos using other tooling as pull requests.

    Note

    We’ve postponed other changes until after React 17. The goal of this release is to enable gradual upgrades. If upgrading to React 17 were too difficult, it would defeat its purpose.

    Changes to Event Delegation

    Technically, it has always been possible to nest apps developed with different versions of React. However, it was rather fragile because of how the React event system worked.

    In React components, you usually write event handlers inline:

    <button onClick={handleClick}>

    The vanilla DOM equivalent to this code is something like:

    myButton.addEventListener('click', handleClick);

    However, for most events, React doesn’t actually attach them to the DOM nodes on which you declare them. Instead, React attaches one handler per event type directly at the document node. This is called event delegation. In addition to its performance benefits on large application trees, it also makes it easier to add new features like replaying events.

    React has been doing event delegation automatically since its first release. When a DOM event fires on the document, React figures out which component to call, and then the React event “bubbles” upwards through your components. But behind the scenes, the native event has already bubbled up to the document level, where React installs its event handlers.

    However, this is a problem for gradual upgrades.

    If you have multiple React versions on the page, they all register event handlers at the top. This breaks e.stopPropagation(): if a nested tree has stopped propagation of an event, the outer tree would still receive it. This made it difficult to nest different versions of React. This concern is not hypothetical — for example, the Atom editor ran into this four years ago.

    This is why we’re changing how React attaches events to the DOM under the hood.

    In React 17, React will no longer attach event handlers at the document level. Instead, it will attach them to the root DOM container into which your React tree is rendered:

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

    In React 16 and earlier, React would do document.addEventListener() for most events. React 17 will call rootNode.addEventListener() under the hood instead.

    A diagram showing how React 17 attaches events to the roots rather than to the document

    Thanks to this change, it is now safer to embed a React tree managed by one version inside a tree managed by a different React version. Note that for this to work, both of the versions would need to be 17 or higher, which is why upgrading to React 17 is important. In a way, React 17 is a “stepping stone” release that makes next gradual upgrades feasible.

    This change also makes it easier to embed React into apps built with other technologies. For example, if the outer “shell” of your app is written in jQuery, but the newer code inside of it is written with React, e.stopPropagation() inside the React code would now prevent it from reaching the jQuery code — as you would expect. This also works in the other direction. If you no longer like React and want to rewrite your app — for example, in jQuery — you can start converting the outer shell from React to jQuery without breaking the event propagation.

    We’ve confirmed that numerous problems reported over the years on our issue tracker related to integrating React with non-React code have been fixed by the new behavior.

    Note

    You might be wondering whether this breaks Portals outside of the root container. The answer is that React also listens to events on portal containers, so this is not an issue.

    Fixing Potential Issues

    As with any breaking change, it is likely some code would need to be adjusted. At Facebook, we had to adjust about 10 modules in total (out of many thousands) to work with this change.

    For example, if you add manual DOM listeners with document.addEventListener(...), you might expect them to catch all React events. In React 16 and earlier, even if you call e.stopPropagation() in a React event handler, your custom document listeners would still receive them because the native event is already at the document level. With React 17, the propagation would stop (as requested!), so your document handlers would not fire:

    document.addEventListener('click', function() {
      // This custom handler will no longer receive clicks
      // from React components that called e.stopPropagation()
    });

    You can fix code like this by converting your listener to use the capture phase. To do this, you can pass { capture: true } as the third argument to document.addEventListener:

    document.addEventListener('click', function() {
      // Now this event handler uses the capture phase,
      // so it receives *all* click events below!
    }, { capture: true });

    Note how this strategy is more resilient overall — for example, it will probably fix existing bugs in your code that happen when e.stopPropagation() is called outside of a React event handler. In other words, event propagation in React 17 works closer to the regular DOM.

    Other Breaking Changes

    We’ve kept the breaking changes in React 17 to the minimum. For example, it doesn’t remove any of the methods that have been deprecated in the previous releases. However, it does include a few other breaking changes that have been relatively safe in our experience. In total, we’ve had to adjust fewer than 20 out of 100,000+ our components because of them.

    Aligning with Browsers

    We’ve made a couple of smaller changes related to the event system:

    • The onScroll event no longer bubbles to prevent common confusion.
    • React onFocus and onBlur events have switched to using the native focusin and focusout events under the hood, which more closely match React’s existing behavior and sometimes provide extra information.
    • Capture phase events (e.g. onClickCapture) now use real browser capture phase listeners.

    These changes align React closer with the browser behavior and improve interoperability.

    Note

    Although React 17 switched from focus to focusin under the hood for the onFocus event, note that this has not affected the bubbling behavior. In React, onFocus event has always bubbled, and it continues to do so in React 17 because generally it is a more useful default. See this sandbox for the different checks you can add for different particular use cases.

    No Event Pooling

    React 17 removes the “event pooling” optimization from React. It doesn’t improve performance in modern browsers and confuses even experienced React users:

    function handleChange(e) {
      setData(data => ({
        ...data,
        // This crashes in React 16 and earlier:
        text: e.target.value
      }));
    }

    This is because React reused the event objects between different events for performance in old browsers, and set all event fields to null in between them. With React 16 and earlier, you have to call e.persist() to properly use the event, or read the property you need earlier.

    In React 17, this code works as you would expect. The old event pooling optimization has been fully removed, so you can read the event fields whenever you need them.

    This is a behavior change, which is why we’re marking it as breaking, but in practice we haven’t seen it break anything at Facebook. (Maybe it even fixed a few bugs!) Note that e.persist() is still available on the React event object, but now it doesn’t do anything.

    Effect Cleanup Timing

    We are making the timing of the useEffect cleanup function more consistent.

    useEffect(() => {
      // This is the effect itself.
      return () => {    // This is its cleanup.  };});

    Most effects don’t need to delay screen updates, so React runs them asynchronously soon after the update has been reflected on the screen. (For the rare cases where you need an effect to block paint, e.g. to measure and position a tooltip, prefer useLayoutEffect.)

    However, when a component is unmounting, effect cleanup functions used to run synchronously (similar to componentWillUnmount being synchronous in classes). We’ve found that this is not ideal for larger apps because it slows down large screen transitions (e.g. switching tabs).

    In React 17, the effect cleanup function always runs asynchronously — for example, if the component is unmounting, the cleanup runs after the screen has been updated.

    This mirrors how the effects themselves run more closely. In the rare cases where you might want to rely on the synchronous execution, you can switch to useLayoutEffect instead.

    Note

    You might be wondering whether this means that you’ll now be unable to fix warnings about setState on unmounted components. Don’t worry — React specifically checks for this case, and does not fire setState warnings in the short gap between unmounting and the cleanup. So code cancelling requests or intervals can almost always stay the same.

    Additionally, React 17 will always execute all effect cleanup functions (for all components) before it runs any new effects. React 16 only guaranteed this ordering for effects within a component.

    Potential Issues

    We’ve only seen a couple of components break with this change, although reusable libraries may need to test it more thoroughly. One example of problematic code may look like this:

    useEffect(() => {
      someRef.current.someSetupMethod();
      return () => {
        someRef.current.someCleanupMethod();
      };
    });

    The problem is that someRef.current is mutable, so by the time the cleanup function runs, it may have been set to null. The solution is to capture any mutable values inside the effect:

    useEffect(() => {
      const instance = someRef.current;
      instance.someSetupMethod();
      return () => {
        instance.someCleanupMethod();
      };
    });

    We don’t expect this to be a common problem because our eslint-plugin-react-hooks/exhaustive-deps lint rule (make sure you use it!) has always warned about this.

    Consistent Errors for Returning Undefined

    In React 16 and earlier, returning undefined has always been an error:

    function Button() {
      return; // Error: Nothing was returned from render
    }

    This is in part because it’s easy to return undefined unintentionally:

    function Button() {
      // We forgot to write return, so this component returns undefined.
      // React surfaces this as an error instead of ignoring it.
      <button />;
    }

    Previously, React only did this for class and function components, but did not check the return values of forwardRef and memo components. This was due to a coding mistake.

    In React 17, the behavior for forwardRef and memo components is consistent with regular function and class components. Returning undefined from them is an error.

    let Button = forwardRef(() => {
      // We forgot to write return, so this component returns undefined.
      // React 17 surfaces this as an error instead of ignoring it.
      <button />;
    });
    
    let Button = memo(() => {
      // We forgot to write return, so this component returns undefined.
      // React 17 surfaces this as an error instead of ignoring it.
      <button />;
    });

    For the cases where you want to render nothing intentionally, return null instead.

    Native Component Stacks

    When you throw an error in the browser, the browser gives you a stack trace with JavaScript function names and their locations. However, JavaScript stacks are often not enough to diagnose a problem because the React tree hierarchy can be just as important. You want to know not just that a Button threw an error, but where in the React tree that Button is.

    To solve this, React 16 started printing “component stacks” when you have an error. Still, they used to be inferior to the native JavaScript stacks. In particular, they were not clickable in the console because React didn’t know where the function was declared in the source code. Additionally, they were mostly useless in production. Unlike regular minified JavaScript stacks which can be automatically restored to the original function names with a sourcemap, with React component stacks you had to choose between production stacks and bundle size.

    In React 17, the component stacks are generated using a different mechanism that stitches them together from the regular native JavaScript stacks. This lets you get the fully symbolicated React component stack traces in a production environment.

    The way React implements this is somewhat unorthodox. Currently, the browsers don’t provide a way to get a function’s stack frame (source file and location). So when React catches an error, it will now reconstruct its component stack by throwing (and catching) a temporary error from inside each of the components above, when it is possible. This adds a small performance penalty for crashes, but it only happens once per component type.

    If you’re curious, you can read more details in this pull request, but for the most part this exact mechanism shouldn’t affect your code. From your perspective, the new feature is that component stacks are now clickable (because they rely on the native browser stack frames), and that you can decode them in production like you would with regular JavaScript errors.

    The part that constitutes a breaking change is that for this to work, React re-executes parts of some of the React functions and React class constructors above in the stack after an error is captured. Since render functions and class constructors shouldn’t have side effects (which is also important for server rendering), this should not pose any practical problems.

    Removing Private Exports

    Finally, the last notable breaking change is that we’ve removed some React internals that were previously exposed to other projects. In particular, React Native for Web used to depend on some internals of the event system, but that dependency was fragile and used to break.

    In React 17, these private exports have been removed. As far as we’re aware, React Native for Web was the only project using them, and they have already completed a migration to a different approach that doesn’t depend on those private exports.

    This means that the older versions of React Native for Web won’t be compatible with React 17, but the newer versions will work with it. In practice, this doesn’t change much because React Native for Web had to release new versions to adapt to internal React changes anyway.

    Additionally, we’ve removed the ReactTestUtils.SimulateNative helper methods. They have never been documented, didn’t do quite what their names implied, and didn’t work with the changes we’ve made to the event system. If you want a convenient way to fire native browser events in tests, check out the React Testing Library instead.

    Installation

    We encourage you to try React 17.0 Release Candidate soon and raise any issues for the problems you might encounter in the migration. Keep in mind that a release candidate is more likely to contain bugs than a stable release, so don’t deploy it to production yet.

    To install React 17 RC with npm, run:

    npm install react@17.0.0-rc.3 react-dom@17.0.0-rc.3

    To install React 17 RC with Yarn, run:

    yarn add react@17.0.0-rc.3 react-dom@17.0.0-rc.3

    We also provide UMD builds of React via a CDN:

    <script crossorigin src="https://unpkg.com/react@17.0.0-rc.3/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17.0.0-rc.3/umd/react-dom.production.min.js"></script>

    Refer to the documentation for detailed installation instructions.

    Changelog

    React

    • Add react/jsx-runtime and react/jsx-dev-runtime for the new JSX transform. (@lunaruan in #18299)
    • Build component stacks from native error frames. (@sebmarkbage in #18561)
    • Allow to specify displayName on context for improved stacks. (@eps1lon in #18224)
    • Prevent 'use strict' from leaking in the UMD bundles. (@koba04 in #19614)
    • Stop using fb.me for redirects. (@cylim in #19598)

    React DOM

    • Delegate events to roots instead of document. (@trueadm in #18195 and others)
    • Clean up all effects before running any next effects. (@bvaughn in #17947)
    • Run useEffect cleanup functions asynchronously. (@bvaughn in #17925)
    • Use browser focusin and focusout for onFocus and onBlur. (@trueadm in #19186)
    • Make all Capture events use the browser capture phase. (@trueadm in #19221)
    • Don’t emulate bubbling of the onScroll event. (@gaearon in #19464)
    • Throw if forwardRef or memo component returns undefined. (@gaearon in #19550)
    • Remove event pooling. (@trueadm in #18969)
    • Stop exposing internals that won’t be needed by React Native Web. (@necolas in #18483)
    • Attach all known event listeners when the root mounts. (@gaearon in #19659)
    • Disable console in the second render pass of DEV mode double render. (@sebmarkbage in #18547)
    • Deprecate the undocumented and misleading ReactTestUtils.SimulateNative API. (@gaearon in #13407)
    • Rename private field names used in the internals. (@gaearon in #18377)
    • Don’t call User Timing API in development. (@gaearon in #18417)
    • Disable console during the repeated render in Strict Mode. (@sebmarkbage in #18547)
    • In Strict Mode, double-render components without Hooks too. (@eps1lon in #18430)
    • Allow calling ReactDOM.flushSync during lifecycle methods (but warn). (@sebmarkbage in #18759)
    • Add the code property to the keyboard event objects. (@bl00mber in #18287)
    • Add the disableRemotePlayback property for video elements. (@tombrowndev in #18619)
    • Add the enterKeyHint property for input elements. (@eps1lon in #18634)
    • Warn when no value is provided to <Context.Provider>. (@charlie1404 in #19054)
    • Warn when memo or forwardRef components return undefined. (@bvaughn in #19550)
    • Improve the error message for invalid updates. (@JoviDeCroock in #18316)
    • Exclude forwardRef and memo from stack frames. (@sebmarkbage in #18559)
    • Improve the error message when switching between controlled and uncontrolled inputs. (@vcarl in #17070)
    • Keep onTouchStart, onTouchMove, and onWheel passive. (@gaearon in #19654)
    • Fix setState hanging in development inside a closed iframe. (@gaearon in #19220)
    • Fix rendering bailout for lazy components with defaultProps. (@jddxf in #18539)
    • Fix a false positive warning when dangerouslySetInnerHTML is undefined. (@eps1lon in #18676)
    • Fix Test Utils with non-standard require implementation. (@just-boris in #18632)
    • Fix onBeforeInput reporting an incorrect event.type. (@eps1lon in #19561)
    • Fix event.relatedTarget reported as undefined in Firefox. (@claytercek in #19607)
    • Fix “unspecified error” in IE11. (@hemakshis in #19664)
    • Fix rendering into a shadow root. (@Jack-Works in #15894)
    • Fix movementX/Y polyfill with capture events. (@gaearon in #19672)
    • Use delegation for onSubmit and onReset events. (@gaearon in #19333)
    • Improve memory usage. (@trueadm in #18970)

    React DOM Server

    • Make useCallback behavior consistent with useMemo for the server renderer. (@alexmckenley in #18783)
    • Fix state leaking when a function component throws. (@pmaccart in #19212)

    React Test Renderer

    • Improve findByType error message. (@henryqdineen in #17439)

    Concurrent Mode (Experimental)

    • Revamp the priority batching heuristics. (@acdlite in #18796)
    • Add the unstable_ prefix before the experimental APIs. (@acdlite in #18825)
    • Remove unstable_discreteUpdates and unstable_flushDiscreteUpdates. (@trueadm in #18825)
    • Remove the timeoutMs argument. (@acdlite in #19703)
    • Disable <div hidden /> prerendering in favor of a different future API. (@acdlite in #18917)
    • Add unstable_expectedLoadTime to Suspense for CPU-bound trees. (@acdlite in #19936)
    • Add an experimental unstable_useOpaqueIdentifier Hook. (@lunaruan in #17322)
    • Add an experimental unstable_startTransition API. (@rickhanlonii in #19696)
    • Using act in the test renderer no longer flushes Suspense fallbacks. (@acdlite in #18596)
    • Use global render timeout for CPU Suspense. (@sebmarkbage in #19643)
    • Clear the existing root content before mounting. (@bvaughn in #18730)
    • Fix a bug with error boundaries. (@acdlite in #18265)
    • Fix a bug causing dropped updates in a suspended tree. (@acdlite in #18384 and #18457)
    • Fix a bug causing dropped render phase updates. (@acdlite in #18537)
    • Fix a bug in SuspenseList. (@sebmarkbage in #18412)
    • Fix a bug causing Suspense fallback to show too early. (@acdlite in #18411)
    • Fix a bug with class components inside SuspenseList. (@sebmarkbage in #18448)
    • Fix a bug with inputs that may cause updates to be dropped. (@jddxf in #18515 and @acdlite in #18535)
    • Fix a bug causing Suspense fallback to get stuck. (@acdlite in #18663)
    • Don’t cut off the tail of a SuspenseList if hydrating. (@sebmarkbage in #18854)
    • Fix a bug in useMutableSource that may happen when getSnapshot changes. (@bvaughn in #18297)
    • Fix a tearing bug in useMutableSource. (@bvaughn in #18912)
    • Warn if calling setState outside of render but before commit. (@sebmarkbage in #18838)
  • React Blog reactjs.org framework javascript react technology web-dev web-development 2020-02-26 00:00
    ↗

    This blog site has been archived. Go to react.dev/blog to see the recent posts. Today we are releasing React 16.13.0. It contains bugfixes and new deprecation warnings to help prepare for a future major release. New Warnings Warnings for some updates during render A React...

    This blog site has been archived. Go to react.dev/blog to see the recent posts.

    Today we are releasing React 16.13.0. It contains bugfixes and new deprecation warnings to help prepare for a future major release.

    New Warnings

    Warnings for some updates during render

    A React component should not cause side effects in other components during rendering.

    It is supported to call setState during render, but only for the same component. If you call setState during a render on a different component, you will now see a warning:

    Warning: Cannot update a component from inside the function body of a different component.

    This warning will help you find application bugs caused by unintentional state changes. In the rare case that you intentionally want to change the state of another component as a result of rendering, you can wrap the setState call into useEffect.

    Warnings for conflicting style rules

    When dynamically applying a style that contains longhand and shorthand versions of CSS properties, particular combinations of updates can cause inconsistent styling. For example:

    <div style={toggle ? 
      { background: 'blue', backgroundColor: 'red' } : 
      { backgroundColor: 'red' }
    }>
      ...
    </div> 

    You might expect this <div> to always have a red background, no matter the value of toggle. However, on alternating the value of toggle between true and false, the background color start as red, then alternates between transparent and blue, as you can see in this demo.

    React now detects conflicting style rules and logs a warning. To fix the issue, don’t mix shorthand and longhand versions of the same CSS property in the style prop.

    Warnings for some deprecated string refs

    String Refs is an old legacy API which is discouraged and is going to be deprecated in the future:

    <Button ref="myRef" />

    (Don’t confuse String Refs with refs in general, which remain fully supported.)

    In the future, we will provide an automated script (a “codemod”) to migrate away from String Refs. However, some rare cases can’t be migrated automatically. This release adds a new warning only for those cases in advance of the deprecation.

    For example, it will fire if you use String Refs together with the Render Prop pattern:

    class ClassWithRenderProp extends React.Component {
      componentDidMount() {
        doSomething(this.refs.myRef);
      }
      render() {
        return this.props.children();
      }
    }
    
    class ClassParent extends React.Component {
      render() {
        return (
          <ClassWithRenderProp>
            {() => <Button ref="myRef" />}
          </ClassWithRenderProp>
        );
      }
    }

    Code like this often indicates bugs. (You might expect the ref to be available on ClassParent, but instead it gets placed on ClassWithRenderProp).

    You most likely don’t have code like this. If you do and it is intentional, convert it to React.createRef() instead:

    class ClassWithRenderProp extends React.Component {
      myRef = React.createRef();
      componentDidMount() {
        doSomething(this.myRef.current);
      }
      render() {
        return this.props.children(this.myRef);
      }
    }
    
    class ClassParent extends React.Component {
      render() {
        return (
          <ClassWithRenderProp>
            {myRef => <Button ref={myRef} />}
          </ClassWithRenderProp>
        );
      }
    }

    Note

    To see this warning, you need to have the babel-plugin-transform-react-jsx-self installed in your Babel plugins. It must only be enabled in development mode.

    If you use Create React App or have the “react” preset with Babel 7+, you already have this plugin installed by default.

    Deprecating React.createFactory

    React.createFactory is a legacy helper for creating React elements. This release adds a deprecation warning to the method. It will be removed in a future major version.

    Replace usages of React.createFactory with regular JSX. Alternately, you can copy and paste this one-line helper or publish it as a library:

    let createFactory = type => React.createElement.bind(null, type);

    It does exactly the same thing.

    Deprecating ReactDOM.unstable_createPortal in favor of ReactDOM.createPortal

    When React 16 was released, createPortal became an officially supported API.

    However, we kept unstable_createPortal as a supported alias to keep the few libraries that adopted it working. We are now deprecating the unstable alias. Use createPortal directly instead of unstable_createPortal. It has exactly the same signature.

    Other Improvements

    Component stacks in hydration warnings

    React adds component stacks to its development warnings, enabling developers to isolate bugs and debug their programs. This release adds component stacks to a number of development warnings that didn’t previously have them. As an example, consider this hydration warning from the previous versions:

    A screenshot of the console warning, simply stating the nature of the hydration mismatch:

    While it’s pointing out an error with the code, it’s not clear where the error exists, and what to do next. This release adds a component stack to this warning, which makes it look like this:

    A screenshot of the console warning, stating the nature of the hydration mismatch, but also including a component stack :

    This makes it clear where the problem is, and lets you locate and fix the bug faster.

    Notable bugfixes

    This release contains a few other notable improvements:

    • In Strict Development Mode, React calls lifecycle methods twice to flush out any possible unwanted side effects. This release adds that behaviour to shouldComponentUpdate. This shouldn’t affect most code, unless you have side effects in shouldComponentUpdate. To fix this, move the code with side effects into componentDidUpdate.
    • In Strict Development Mode, the warnings for usage of the legacy context API didn’t include the stack for the component that triggered the warning. This release adds the missing stack to the warning.
    • onMouseEnter now doesn’t trigger on disabled <button> elements.
    • ReactDOM was missing a version export since we published v16. This release adds it back. We don’t recommend using it in your application logic, but it’s useful when debugging issues with mismatching / multiple versions of ReactDOM on the same page.

    We’re thankful to all the contributors who helped surface and fix these and other issues. You can find the full changelog below.

    Installation

    React

    React v16.13.0 is available on the npm registry.

    To install React 16 with Yarn, run:

    yarn add react@^16.13.0 react-dom@^16.13.0

    To install React 16 with npm, run:

    npm install --save react@^16.13.0 react-dom@^16.13.0

    We also provide UMD builds of React via a CDN:

    <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>

    Refer to the documentation for detailed installation instructions.

    Changelog

    React

    • Warn when a string ref is used in a manner that’s not amenable to a future codemod (@lunaruan in #17864)
    • Deprecate React.createFactory() (@trueadm in #17878)

    React DOM

    • Warn when changes in style may cause an unexpected collision (@sophiebits in #14181, #18002)
    • Warn when a function component is updated during another component’s render phase (@acdlite in #17099)
    • Deprecate unstable_createPortal (@trueadm in #17880)
    • Fix onMouseEnter being fired on disabled buttons (@AlfredoGJ in #17675)
    • Call shouldComponentUpdate twice when developing in StrictMode (@bvaughn in #17942)
    • Add version property to ReactDOM (@ealush in #15780)
    • Don’t call toString() of dangerouslySetInnerHTML (@sebmarkbage in #17773)
    • Show component stacks in more warnings (@gaearon in #17922, #17586)

    Concurrent Mode (Experimental)

    • Warn for problematic usages of ReactDOM.createRoot() (@trueadm in #17937)
    • Remove ReactDOM.createRoot() callback params and added warnings on usage (@bvaughn in #17916)
    • Don’t group Idle/Offscreen work with other work (@sebmarkbage in #17456)
    • Adjust SuspenseList CPU bound heuristic (@sebmarkbage in #17455)
    • Add missing event plugin priorities (@trueadm in #17914)
    • Fix isPending only being true when transitioning from inside an input event (@acdlite in #17382)
    • Fix React.memo components dropping updates when interrupted by a higher priority update (@acdlite in #18091)
    • Don’t warn when suspending at the wrong priority (@gaearon in #17971)
    • Fix a bug with rebasing updates (@acdlite and @sebmarkbage in #17560, #17510, #17483, #17480)
  • End of feed
Maibook — your private personalized AI community
  • rcanand.com
  • mlaillc.com
  • @rcanand (X)
  • LinkedIn
  • Feedback
  • Credits