react changelog


Hey there, code wizards and bug squashers! πŸŽ‰ We've got some exciting updates and fixes rolling out, so buckle up and let's dive into the latest changes that will make your coding life a whole lot smoother.

New Features and Improvements

  • Constant Propagation for Template Literals: The compiler now smartly inlines template literals that are made up entirely of constant values. This means those backticks are swapped for double quotes, letting expressions like "" === "" and `a${1}` equal "a1" evaluate as true. It's like magic but with fewer rabbits and more code optimization! πŸͺ„

  • TypeScript Support for MCP Plugins: We've added TypeScript support to enhance the development experience, making your code more robust and maintainable. This is part of a series of updates, ensuring a smooth transition to better code quality. πŸ“¦

  • React DevTools Highlighting with Popover API: No more hiding behind top-layer elements! The highlighting in React DevTools now uses the Popover API to ensure updates are visible above everything else. It’s like giving your components the spotlight they deserve. 🌟

  • Event Dispatching for Fragment Instances: Fragment instances can now dispatch events to their host parent element, simulating event bubbling. If the parent is disconnected, you'll get a heads-up with a developer warning. πŸš€

  • Focus Management in FragmentInstances: We've improved the focus capabilities by allowing focus and focusLast methods to work on nested host components. Now you can target deeply nested elements without breaking a sweat. πŸ”

  • Constant Folding for Unary Minus: The compiler now optimizes unary minus operations by folding them into constant * -1, even handling tricky cases like -0 to 0. Say goodbye to unnecessary calculations! βž–

  • Event Replay Between Commits: Your controlled inputs are safe! We've introduced event replaying between commits to preserve user interactions during hydration. Your forms will thank you. πŸ“

  • Compare Document Position for Fragments: Fragment instances can now use compareDocumentPosition to determine their relationship with other nodes, making DOM interactions even more intuitive. πŸ“œ

Bugfixes

  • Emoji Handling in JSX Attributes: Fixed an issue with JSX attributes containing emojis and extended Unicode characters. Now they’re correctly wrapped in expression containers, ensuring your UI is as expressive as your emojis. 😎

  • Prevent Serialized Size Leakage: We've patched a bug preventing serialized size information from leaking across requests in the React Server DOM. Your data stays where it should, no surprises! πŸ”’

  • Mutable Range Handling in Functions: Functions capturing mutable values but not called now have their mutable ranges correctly inferred, preventing unnecessary memo scope grouping and ensuring reactive scopes are created when needed. πŸ”„

Chores

  • ESLint Plugin for React Hooks Update: The build process now includes the eslint plugin in the fbsource output, keeping lint rules in sync with internal standards. It’s all about keeping things tidy and consistent. 🧹

That's all for now, folks! Keep coding, keep innovating, and don't forget to enjoy the little wins along the way. Happy coding! 🎈

Included Commits

2025-05-02T17:56:45 See commit

The commit titled "[mcp] Update plugins (#33082)" introduces TypeScript support to the project. This enhancement aims to improve the development experience by leveraging TypeScript's static typing features, which can lead to more robust and maintainable code.

Additionally, the commit is part of a series of related changes, as indicated by the references to other pull requests (#33085, #33084, #33083, and #33101). The updates are organized within a stack, suggesting a coordinated effort to implement these enhancements effectively.

Files changed

2025-05-02T20:03:06 See commit

The commit titled "[eslint-plugin-react-hooks] update fbsource build (#33104)" focuses on updating the build process to include the eslint plugin within the fbsource output. This change aims to ensure that the lint rules are synchronized directly with internal requirements. The modifications involve altering the GitHub workflow configuration to copy the eslint-plugin-react-hooks directory into the compiled output, rather than moving it, which allows for the inclusion of the full package along with its dependencies.

Key changes in the workflow include the creation of a new directory for eslint-plugin-react-hooks and the copying of the necessary files from the build output, ensuring that the internal version contains all required components. This update reflects a shift in how the eslint-plugin-react-hooks is handled within the fbsource build, enhancing consistency and alignment with internal standards.

Files changed

  • .github/workflows/runtime_commit_artifacts.yml
2025-05-03T00:07:50 See commit

This commit addresses an issue in the JSX attribute handling within the React compiler related to string values that include emojis and other characters from the astral plane of Unicode. Previously, the regex used to determine whether a string attribute required wrapping in an expression container only accounted for the basic Unicode character plane, which resulted in improper handling of emojis and similar characters. The update expands the regex to include characters from the astral plane, ensuring that any string containing these characters is correctly wrapped in an expression container.

As a result of this fix, JSX components can now correctly process string attributes that contain emojis, enhancing the flexibility and usability of the JSX syntax in React. The changes include modifications to the regex pattern in the code generation logic, as well as updates to test fixtures to verify the correct handling of string attributes with extended Unicode characters, including emojis.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-string-attribute-expression-container.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-string-attribute-expression-container.js
2025-05-03T00:15:32 See commit

This commit addresses an issue in the React compiler related to handling functions that capture mutable values but are never called. In such cases, the compiler previously did not infer a mutable range for these functions, leading to a lack of aliasing between the function and its mutable captures. This could result in unnecessary grouping of memo scopes or, conversely, the failure to create a reactive scope when there is a known mutation. The commit introduces a mechanism that identifies function expressions and object methods with empty mutable ranges and known-mutable operands, ensuring they are aliased together and that their mutable ranges are updated appropriately.

To illustrate the problem and solution, the commit includes examples of hooks that demonstrate both scenarios: one where a function might appear to mutate a value and another where it is confirmed to do so. The newly implemented logic ensures that when a function is defined to mutate a value (like caching in a WeakMap), both the function and its mutable captures are correctly associated within the same reactive scope. This change enhances the compiler's ability to manage mutable references, improving the reliability of memoization in React hooks while adhering to the necessary constraints of immutability and purity in functional programming.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/Inference/InerAliasForUncalledFunctions.ts
  • compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutableRanges.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-uncalled-function-capturing-mutable-values-memoizes-with-captures-values.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-uncalled-function-capturing-mutable-values-memoizes-with-captures-values.js
2025-05-05T16:30:33 See commit

The commit titled "Prevent serialized size leaking across requests" addresses an issue in the React Server DOM framework, specifically focusing on preventing the leakage of serialized size information between different requests. The changes include modifications to the testing framework and the core server logic. A new regression test was added to ensure that the serialized size of a model does not carry over from one request to another, which could lead to unexpected behavior in rendering. The test simulates a scenario where a long text string is processed, and it confirms that the serialized size remains consistent across multiple requests.

In the code modifications, the logic for handling the serialized size during task processing was refined. The previous approach involved stashing the outer parent size and restoring it after processing, which could potentially lead to incorrect size calculations. The updated logic simplifies this by ensuring that the serialized size is correctly managed without unnecessary complexity, thereby improving the reliability of the rendering process. Overall, this commit enhances the robustness of the React Server DOM by addressing a critical issue related to serialized size management.

Files changed

  • packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js
  • packages/react-server/src/ReactFlightServer.js
2025-05-06T04:23:27 See commit

This commit introduces a new feature in React that allows for event replaying between commits, specifically targeting scenarios where user interactions with controlled inputs may be lost during hydration. By implementing a mechanism that flushes events at the end of the flushSpawned work, the changes ensure that user-entered values are preserved even if a rerender occurs due to state changes before the hydration process completes. This is particularly crucial for maintaining the integrity of user input in forms, addressing a common issue where inputs reset to their initial state after hydration.

The code modifications include updates to several files, enhancing the event replaying functionality and adding tests to verify that user interactions remain intact during cascading updates. The changes involve the addition of new functions to manage event flushing and adjustments to existing components to handle state updates correctly. Overall, this commit aims to improve the user experience by preventing the loss of input data during the hydration phase of React components, particularly for controlled inputs.

Files changed

  • fixtures/ssr/src/components/Page.js
  • packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
  • packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js
  • packages/react-dom/src/__tests__/ReactDOMServerIntegrationUserInteraction-test.js
  • packages/react-reconciler/src/ReactFiberConfigWithNoHydration.js
  • packages/react-reconciler/src/ReactFiberWorkLoop.js
  • packages/react-reconciler/src/forks/ReactFiberConfig.custom.js
2025-05-06T17:01:40 See commit

This commit introduces the compareDocumentPosition(otherNode) method for fragment instances, enhancing their functionality to align with typical element positioning in the DOM, while incorporating specific behaviors for fragments. The implementation defines various positional relationships, such as distinguishing when an element is before or after a fragment, contained within it, or when the fragment is empty. The behavior is validated through unit tests that outline the expected outcomes for different scenarios, ensuring that the method accurately reflects the relationship between nodes and fragments.

The changes affect multiple files within the React ecosystem, including modifications to the React Fiber configuration for both DOM and Fabric, updates to the DOM plugin event system, and adjustments to the React Fiber tree reflection. These updates collectively enhance the handling of fragments in React, allowing for more precise comparisons and interactions with the DOM structure.

Files changed

  • packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
  • packages/react-dom-bindings/src/events/DOMPluginEventSystem.js
  • packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js
  • packages/react-native-renderer/src/ReactFiberConfigFabric.js
  • packages/react-reconciler/src/ReactFiberTreeReflection.js
2025-05-07T14:48:17 See commit

The recent commit titled "[DevTools] Use Popover API for TraceUpdates highlighting" addresses a significant issue within React DevTools where component update highlights were obscured by top-layer elements, such as <dialog> components or those utilizing the Popover API. This enhancement ensures that the highlighting of component updates remains visible above all other content, thereby improving the user experience for developers debugging their applications. The implementation leverages the Popover API while still maintaining backward compatibility for browsers that do not support it, ensuring that the functionality remains intact across different environments.

To validate the changes, the author conducted thorough testing, including manual tests in Chrome with Popover API support and in other browsers lacking this support to confirm fallback behavior. Additionally, the React DevTools test suite was executed, with all tests passing successfully, indicating no regressions. The commit also introduces a new test application that demonstrates the highlighting functionality, providing a practical way for users to verify the updates in real-time. Overall, this commit enhances the usability of React DevTools, making it easier for developers to identify component updates during debugging sessions.

Files changed

  • packages/react-devtools-extensions/chrome/manifest.json
  • packages/react-devtools-extensions/edge/manifest.json
  • packages/react-devtools-shared/src/backend/views/TraceUpdates/canvas.js
  • packages/react-devtools-shell/src/app/TraceUpdatesTest/index.js
  • packages/react-devtools-shell/src/app/index.js
2025-05-07T16:47:28 See commit

This commit enhances the functionality of FragmentInstances in React by allowing their focus and focusLast methods to search for focusable nested host components in a depth-first manner. Previously, these methods only attempted to focus on the first level of host children, which limited their effectiveness. With this update, if a focus attempt on a child is successful, the search will terminate, improving the efficiency of focus handling in complex component structures. For instance, in a Menu component containing multiple MenuItem components, the focus can now directly target the first or last anchor (<a>) tags without unnecessary checks on wrapping elements.

The changes include the introduction of a new traversal function, traverseFragmentInstanceDeeply, which recursively checks all nested children of a FragmentInstance. Additionally, the commit includes updates to test cases to verify the new focus behavior, ensuring that deeply nested focusable elements can be targeted appropriately. The modifications also encompass adjustments in related files, such as CSS for visual feedback on focused elements and updates to existing test fixtures to validate the new functionality. Overall, this commit significantly improves the usability of focus management within nested React components.

Files changed

  • fixtures/dom/src/components/fixtures/fragment-refs/FocusCase.js
  • fixtures/dom/src/style.css
  • packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
  • packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js
  • packages/react-reconciler/src/ReactFiberTreeReflection.js
2025-05-07T17:15:11 See commit

This commit introduces constant folding for the unary minus operator in the compiler, specifically for UnaryExpression nodes. Previously, unary minus was not included in the constant folding process. With this update, if the operand of the unary minus is a constant number, the expression is transformed to constant * -1. This enhancement also addresses the specific case of coercing -0 to 0, ensuring that comparisons like 0 === -0 evaluate to true during constant propagation.

The implementation has been validated through attached tests, which confirm that the changes correctly optimize expressions involving unary minus. The modifications affect several files, including updates to the constant propagation logic and the addition of new test cases that demonstrate the expected behavior of the compiler when handling unary minus operations. The tests include various scenarios, ensuring comprehensive coverage of edge cases, such as operations involving -0, -Infinity, and NaN.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary-number.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary-number.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-unary.expect.md
2025-05-07T18:00:59 See commit

The commit introduces a new method, dispatchEvent, to fragment instances, allowing them to trigger events on their host parent element. This method simulates event bubbling, enabling the fragment instance to effectively handle events as if it were capable of receiving them directly. If the parent element is disconnected from the DOM, a developer warning is issued, and the event will not be dispatched.

In addition to the new method, several files were modified to implement this feature, including updates to the event dispatching logic in the React Fiber configuration and adjustments in test cases to ensure proper functionality. New test cases were also added to verify the behavior of the dispatchEvent method within the context of fragment references.

Files changed

  • fixtures/dom/src/components/fixtures/fragment-refs/EventDispatchCase.js
  • fixtures/dom/src/components/fixtures/fragment-refs/index.js
  • packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
  • packages/react-dom/src/__tests__/ReactDOMFragmentRefs-test.js
2025-05-08T16:24:22 See commit

The commit introduces a feature to the compiler that implements constant propagation specifically for template literals. With this enhancement, template literals that consist entirely of constant values are inlined as string literals, effectively replacing the backtick syntax with double quotes. This change allows for further optimization in constant propagation, enabling expressions like "" === "" to evaluate as true and template literals such as `a${1}` to simplify to "a1". However, if a template literal can only be partially evaluated, or contains non-constant values like arrays, objects, or functions, it is left unchanged to avoid complications in dead code elimination and constant folding processes.

The implementation includes modifications to the ConstantPropagation.ts file, where the logic for evaluating template literals has been added. The commit also introduces new tests to validate the functionality, ensuring that various scenarios involving template literals are correctly handled. Overall, this update enhances the compiler's ability to optimize code by recognizing and simplifying constant expressions involving template literals.

Files changed

  • compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-template-literal.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-propagation-template-literal.js
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/labeled-break-within-label-switch.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequential-destructuring-assignment-to-scope-declarations.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/sequential-destructuring-both-mixed-local-and-scope-declaration.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/template-literal.expect.md
  • compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/unlabeled-break-within-label-switch.expect.md