From 9de0304ad72bc3f8a77d2d84efa530b8051d1c15 Mon Sep 17 00:00:00 2001 From: Jan Kassens Date: Fri, 2 May 2025 16:52:17 -0400 Subject: [PATCH 1/4] Add missing copyright header (#33106) This made the build fail since there was no file header comment. --- packages/eslint-plugin-react-hooks/npm/index.d.ts | 7 +++++++ packages/eslint-plugin-react-hooks/npm/index.js | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/packages/eslint-plugin-react-hooks/npm/index.d.ts b/packages/eslint-plugin-react-hooks/npm/index.d.ts index 62ca164ec2..17bdf95c51 100644 --- a/packages/eslint-plugin-react-hooks/npm/index.d.ts +++ b/packages/eslint-plugin-react-hooks/npm/index.d.ts @@ -1 +1,8 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + export * from './cjs/eslint-plugin-react-hooks'; diff --git a/packages/eslint-plugin-react-hooks/npm/index.js b/packages/eslint-plugin-react-hooks/npm/index.js index 20458a7a9b..b819fc7023 100644 --- a/packages/eslint-plugin-react-hooks/npm/index.js +++ b/packages/eslint-plugin-react-hooks/npm/index.js @@ -1,3 +1,10 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + 'use strict'; // TODO: this doesn't make sense for an ESLint rule. From e39b380a21aa4ef48d5880aa2c800ec5b1b044bd Mon Sep 17 00:00:00 2001 From: lauren Date: Fri, 2 May 2025 16:54:17 -0400 Subject: [PATCH 2/4] [mcp] Fix unresolved imports (#33105) We need to explicitly import the modules so they'll be inlined correctly into the bundle. --- .../react-mcp-server/src/tools/runtimePerf.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/packages/react-mcp-server/src/tools/runtimePerf.ts b/compiler/packages/react-mcp-server/src/tools/runtimePerf.ts index bc46f496ec..7f4d0a1efe 100644 --- a/compiler/packages/react-mcp-server/src/tools/runtimePerf.ts +++ b/compiler/packages/react-mcp-server/src/tools/runtimePerf.ts @@ -1,5 +1,11 @@ import * as babel from '@babel/core'; import puppeteer from 'puppeteer'; +// @ts-ignore +import * as babelPresetTypescript from '@babel/preset-typescript'; +// @ts-ignore +import * as babelPresetEnv from '@babel/preset-env'; +// @ts-ignore +import * as babelPresetReact from '@babel/preset-react'; type PerformanceResults = { renderTime: number; @@ -25,15 +31,11 @@ export async function measurePerformance( code: string, iterations: number, ): Promise { - const babelOptions = { + const babelOptions: babel.TransformOptions = { filename: 'anonymous.tsx', configFile: false, babelrc: false, - presets: [ - '@babel/preset-typescript', - '@babel/preset-env', - '@babel/preset-react', - ], + presets: [babelPresetTypescript, babelPresetEnv, babelPresetReact], }; const parsed = await babel.parseAsync(code, babelOptions); From f0ca53d1337780ccfd49c132170d378c789cb463 Mon Sep 17 00:00:00 2001 From: Jan Kassens Date: Fri, 2 May 2025 17:05:56 -0400 Subject: [PATCH 3/4] [eslint-plugin-react-hooks] another CI update... (#33107) We currently created a nested directory, this should remove that. See: https://github.com/facebook/react/tree/builds/facebook-fbsource/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/eslint-plugin-react-hooks/eslint-plugin-react-hooks --- .github/workflows/runtime_commit_artifacts.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/runtime_commit_artifacts.yml b/.github/workflows/runtime_commit_artifacts.yml index a1c739331b..24bb897f8c 100644 --- a/.github/workflows/runtime_commit_artifacts.yml +++ b/.github/workflows/runtime_commit_artifacts.yml @@ -170,9 +170,7 @@ jobs: # Copy eslint-plugin-react-hooks # NOTE: This is different from www, here we include the full package # including package.json to include dependencies in fbsource. - mkdir $BASE_FOLDER/RKJSModules/vendor/react/eslint-plugin-react-hooks - cp -r build/oss-experimental/eslint-plugin-react-hooks \ - $BASE_FOLDER/RKJSModules/vendor/react/eslint-plugin-react-hooks + cp -r build/oss-experimental/eslint-plugin-react-hooks $BASE_FOLDER/RKJSModules/vendor/react # Move React Native version file mv build/facebook-react-native/VERSION_NATIVE_FB ./compiled-rn/VERSION_NATIVE_FB From 7a12f071a702cdac5a293b6ea4cb39d0992658d0 Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Fri, 2 May 2025 17:36:14 -0400 Subject: [PATCH 4/4] [mcp] Prompt improvements for smarter tool composition Our runtime results are still bogus, but so far this tweak let's the llm use the tools a little more intelligently. example: --- ```js import React from 'react'; function App() { const [count, setCount] = React.useState(0); const [data, setData] = React.useState([]); React.useEffect(() => { const processData = () => { console.log("Processing data..."); const newData = []; for (let i = 0; i < 1000000000; i++) { newData.push({ id: i, value: Math.random() * count }); } return newData; }; const processedData = processData(); setData(processedData); }, [count]); return (

Count: {count}

Data Length: {data.length}

    {data.slice(0, 5).map((item) => (
  • Item {item.id}: {item.value.toFixed(2)}
  • ))}
); }; ``` why is this component slow? use the react tools to figure this out. > I'll analyze why this component is slow using the React tools. Let's first evaluate the performance of the original code. [review-react-runtime ...] The performance measurement tool timed out, which is a strong indication of just how severe the performance issue is in this component. Let's now try to compile the code to see if React Compiler can identify any issues: [compile...] Now I understand the issue. Let's analyze why this component is extremely slow: Main Performance Issues: Massive Data Processing: The component is trying to create an array with a billion (1,000,000,000) objects in the processData function. This is an enormous amount of data that will: Consume massive amounts of memory Take an extremely long time to process Likely crash the browser Unnecessary Recalculation: The effect depends on [count], meaning every time the count changes, it will reprocess this enormous dataset. Inefficient Data Handling: Even though only 5 items are displayed, the component processes a billion items. Let's fix these issues: [compile...] Now let's check if our modified code performs better: [review-react-runtime...] Excellent! The performance has dramatically improved. Now let's check the React documentation to make sure we're following the best practices: [query-react-dev-docs...] --- .../packages/react-mcp-server/src/index.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/packages/react-mcp-server/src/index.ts b/compiler/packages/react-mcp-server/src/index.ts index e250770c15..138dc57dc1 100644 --- a/compiler/packages/react-mcp-server/src/index.ts +++ b/compiler/packages/react-mcp-server/src/index.ts @@ -29,7 +29,7 @@ const server = new McpServer({ server.tool( 'query-react-dev-docs', - 'This tool lets you search for official docs from react.dev. This always has the most up to date information on React. You can look for documentation on APIs such as , , and hooks like useOptimistic, useSyncExternalStore, useTransition, and more. Whenever you think hard about React, please use this tool to get more information before proceeding.', + 'This tool lets you search for official docs from react.dev. This always has the most up to date information on React. You can look for documentation on APIs such as , , and hooks like useOptimistic, useSyncExternalStore, useTransition, and more. Whenever you think hard about React, use this tool to get more information before proceeding.', { query: z.string(), }, @@ -72,7 +72,15 @@ server.tool( server.tool( 'compile', - 'Compile code with React Compiler. This tool will return the compiled output, which is automatically memoized React components and hooks, written in JavaScript or TypeScript. You can run this tool whenever you want to check if some React code will compile successfully. You can also run this tool every time you make a suggestion to code, to see how it affects the compiled output. If the compiler returns a diagnostic message, you should read the diagnostic message and try to fix the code and run the compiler again to verify.', + `Compile code with React Compiler. This tool will return the compiled output, which is automatically memoized React components and hooks, written in JavaScript or TypeScript. You can run this tool whenever you want to check if some React code will compile successfully. You can also run this tool every time you make a suggestion to code, to see how it affects the compiled output. If the compiler returns a diagnostic message, you should read the diagnostic message and try to fix the code and run the compiler again to verify. After compiling code successfully, you should run it through the review-react-runtime to verify the compiled code is faster than the original. + + + When you encounter a bailout or diagnostic message, first think and try to understand where the error is coming from. You can use tools such as puppeteer if available to browse the documentation links provided in the diagnostic, and then read that information to understand the error in more detail. You can propose fixes after doing so. + + This is a non-exhaustive list of bailouts where you should take specific actions: + - React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved: fix this by first removing the manual memo (useMemo/useCallback) and then try compiling again. use the review-react-runtime tool to verify that the compiled code can run without crashing. if it crashes, the original code likely breaks the Rules of React and so cannot be safely compiled. + + `, { text: z.string(), passName: z.enum(['HIR', 'ReactiveFunction', 'All', '@DEBUG']).optional(), @@ -278,6 +286,7 @@ server.tool( server.tool( 'review-react-runtime', `Run this tool every time you propose a performance related change to verify if your suggestion actually improves performance. + This tool has some requirements on the code input: - The react code that is passed into this tool MUST contain an App functional component without arrow function. @@ -298,12 +307,12 @@ server.tool( (repeat until every metric is good or two consecutive cycles show no gain) - - Apply one focused change based on the failing metric plus React-specific guidance: + - Always run the tool once on the original code before any modification + - Run the tool again after making the modification, and apply one focused change based on the failing metric plus React-specific guidance: - LCP: lazy-load off-screen images, inline critical CSS, preconnect, use React.lazy + Suspense for below-the-fold modules. if the user requests for it, use React Server Components for static content (Server Components). - INP: wrap non-critical updates in useTransition, avoid calling setState inside useEffect. - CLS: reserve space via explicit width/height or aspect-ratio, keep stable list keys, use fixed-size skeleton loaders, animate only transform/opacity, avoid inserting ads or banners without placeholders. - - Stop when every metric is classified as good. Return the final metric table and the list of applied changes. + - Compare the results of your modified code compared to the original to verify that your changes have improved performance. `, {