Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Read the [React 19.2 release post](https://react.dev/blog/2025/10/01/react-19-2)
- [`<Activity>`](https://react.dev/reference/react/Activity): A new API to hide and restore the UI and internal state of its children.
- [`useEffectEvent`](https://react.dev/reference/react/useEffectEvent) is a React Hook that lets you extract non-reactive logic into an [Effect Event](https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event).
- [`cacheSignal`](https://react.dev/reference/react/cacheSignal) (for RSCs) lets your know when the `cache()` lifetime is over.
- [React Performance tracks](https://react.dev/reference/developer-tooling/react-performance-tracks) appear on the Performance panel’s timeline in your browser developer tools
- [React Performance tracks](https://react.dev/reference/dev-tools/react-performance-tracks) appear on the Performance panel’s timeline in your browser developer tools

### New React DOM Features

Expand Down
4 changes: 2 additions & 2 deletions compiler/packages/babel-plugin-react-compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
"react-dom": "0.0.0-experimental-4beb1fd8-20241118",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.2",
"zod": "^3.22.4 || ^4.0.0",
"zod-validation-error": "^3.0.3 || ^4.0.0"
"zod": "^3.25.0 || ^4.0.0",
"zod-validation-error": "^3.5.0 || ^4.0.0"
},
"resolutions": {
"./**/@babel/parser": "7.7.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import * as t from '@babel/types';
import {z} from 'zod';
import {z} from 'zod/v4';
import {
CompilerDiagnostic,
CompilerError,
Expand All @@ -20,7 +20,7 @@ import {
tryParseExternalFunction,
} from '../HIR/Environment';
import {hasOwnProperty} from '../Utils/utils';
import {fromZodError} from 'zod-validation-error';
import {fromZodError} from 'zod-validation-error/v4';
import {CompilerPipelineValue} from './Pipeline';

const PanicThresholdOptionsSchema = z.enum([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
*/

import * as t from '@babel/types';
import {ZodError, z} from 'zod';
import {fromZodError} from 'zod-validation-error';
import {ZodError, z} from 'zod/v4';
import {fromZodError} from 'zod-validation-error/v4';
import {CompilerError} from '../CompilerError';
import {Logger, ProgramContext} from '../Entrypoint';
import {Err, Ok, Result} from '../Utils/Result';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {assertExhaustive} from '../Utils/utils';
import {Environment, ReactFunctionType} from './Environment';
import type {HookKind} from './ObjectShape';
import {Type, makeType} from './Types';
import {z} from 'zod';
import {z} from 'zod/v4';
import type {AliasingEffect} from '../Inference/AliasingEffects';
import {isReservedWord} from '../Utils/Keyword';
import {Err, Ok, Result} from '../Utils/Result';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import {isValidIdentifier} from '@babel/types';
import {z} from 'zod';
import {z} from 'zod/v4';
import {Effect, ValueKind} from '..';
import {
EffectSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import {fromZodError} from 'zod-validation-error';
import {fromZodError} from 'zod-validation-error/v4';
import {CompilerError} from '../CompilerError';
import {
CompilationMode,
Expand Down
4 changes: 2 additions & 2 deletions compiler/packages/eslint-plugin-react-compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"@babel/core": "^7.24.4",
"@babel/parser": "^7.24.4",
"hermes-parser": "^0.25.1",
"zod": "^3.22.4 || ^4.0.0",
"zod-validation-error": "^3.0.3 || ^4.0.0"
"zod": "^3.25.0 || ^4.0.0",
"zod-validation-error": "^3.5.0 || ^4.0.0"
},
"devDependencies": {
"@babel/preset-env": "^7.22.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ import {defineConfig} from 'tsup';
export default defineConfig({
entry: ['./src/index.ts'],
outDir: './dist',
external: ['@babel/core', 'hermes-parser', 'zod', 'zod-validation-error'],
external: [
'@babel/core',
'hermes-parser',
'zod',
'zod/v4',
'zod-validation-error',
'zod-validation-error/v4',
],
splitting: false,
sourcemap: false,
dts: false,
Expand Down
4 changes: 2 additions & 2 deletions compiler/packages/react-compiler-healthcheck/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"fast-glob": "^3.3.2",
"ora": "5.4.1",
"yargs": "^17.7.2",
"zod": "^3.22.4 || ^4.0.0",
"zod-validation-error": "^3.0.3 || ^4.0.0"
"zod": "^3.25.0 || ^4.0.0",
"zod-validation-error": "^3.5.0 || ^4.0.0"
},
"devDependencies": {},
"engines": {
Expand Down
2 changes: 2 additions & 0 deletions compiler/packages/react-compiler-healthcheck/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ export default defineConfig({
'ora',
'yargs',
'zod',
'zod/v4',
'zod-validation-error',
'zod-validation-error/v4',
],
splitting: false,
sourcemap: false,
Expand Down
2 changes: 1 addition & 1 deletion compiler/packages/react-mcp-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"html-to-text": "^9.0.5",
"prettier": "^3.3.3",
"puppeteer": "^24.7.2",
"zod": "^3.22.4 || ^4.0.0"
"zod": "^3.25.0 || ^4.0.0"
},
"devDependencies": {
"@types/html-to-text": "^9.0.4",
Expand Down
2 changes: 1 addition & 1 deletion compiler/packages/react-mcp-server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import {McpServer} from '@modelcontextprotocol/sdk/server/mcp.js';
import {StdioServerTransport} from '@modelcontextprotocol/sdk/server/stdio.js';
import {z} from 'zod';
import {z} from 'zod/v4';
import {compile, type PrintedCompilerPipelineValue} from './compiler';
import {
CompilerPipelineValue,
Expand Down
4 changes: 3 additions & 1 deletion compiler/packages/snap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
"react": "0.0.0-experimental-4beb1fd8-20241118",
"react-dom": "0.0.0-experimental-4beb1fd8-20241118",
"readline": "^1.3.0",
"yargs": "^17.7.1"
"yargs": "^17.7.1",
"zod": "^3.25.0 || ^4.0.0",
"zod-validation-error": "^3.5.0 || ^4.0.0"
},
"devDependencies": {
"@babel/core": "^7.19.1",
Expand Down
4 changes: 2 additions & 2 deletions compiler/packages/snap/src/sprout/evaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {render} from '@testing-library/react';
import {JSDOM} from 'jsdom';
import React, {MutableRefObject} from 'react';
import util from 'util';
import {z} from 'zod';
import {fromZodError} from 'zod-validation-error';
import {z} from 'zod/v4';
import {fromZodError} from 'zod-validation-error/v4';
import {initFbt, toJSON} from './shared-runtime';

/**
Expand Down
12 changes: 6 additions & 6 deletions compiler/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11505,17 +11505,17 @@ zod-to-json-schema@^3.24.1:
resolved "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz"
integrity sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==

"zod-validation-error@^3.0.3 || ^4.0.0":
"zod-validation-error@^3.5.0 || ^4.0.0":
version "4.0.2"
resolved "https://registry.yarnpkg.com/zod-validation-error/-/zod-validation-error-4.0.2.tgz#bc605eba49ce0fcd598c127fee1c236be3f22918"
integrity sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==

"zod@^3.22.4 || ^4.0.0":
version "4.1.11"
resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.11.tgz#4aab62f76cfd45e6c6166519ba31b2ea019f75f5"
integrity sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==

zod@^3.23.8, zod@^3.24.1:
version "3.24.3"
resolved "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz"
integrity sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==

"zod@^3.25.0 || ^4.0.0":
version "4.1.12"
resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.12.tgz#64f1ea53d00eab91853195653b5af9eee68970f0"
integrity sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,17 @@ const allTests = {
`,
errors: [useEffectEventError('onClick', false)],
},
{
code: normalizeIndent`
// Invalid because useEffectEvent is being passed down
function MyComponent({ theme }) {
return <Child onClick={useEffectEvent(() => {
showNotification(theme);
})} />;
}
`,
errors: [{...useEffectEventError(null, false), line: 4}],
},
{
code: normalizeIndent`
// This should error even though it shares an identifier name with the below
Expand Down Expand Up @@ -1726,6 +1737,14 @@ function classError(hook) {
}

function useEffectEventError(fn, called) {
if (fn === null) {
return {
message:
`React Hook "useEffectEvent" can only be called at the top level of your component.` +
` It cannot be passed down.`,
};
}

return {
message:
`\`${fn}\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin-react-hooks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"@babel/core": "^7.24.4",
"@babel/parser": "^7.24.4",
"hermes-parser": "^0.25.1",
"zod": "^3.22.4 || ^4.0.0",
"zod-validation-error": "^3.0.3 || ^4.0.0"
"zod": "^3.25.0 || ^4.0.0",
"zod-validation-error": "^3.5.0 || ^4.0.0"
},
"devDependencies": {
"@babel/eslint-parser": "^7.11.4",
Expand Down
26 changes: 25 additions & 1 deletion packages/eslint-plugin-react-hooks/src/rules/RulesOfHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,15 @@ function isUseEffectEventIdentifier(node: Node): boolean {
return node.type === 'Identifier' && node.name === 'useEffectEvent';
}

function useEffectEventError(fn: string, called: boolean): string {
function useEffectEventError(fn: string | null, called: boolean): string {
// no function identifier, i.e. it is not assigned to a variable
if (fn === null) {
return (
`React Hook "useEffectEvent" can only be called at the top level of your component.` +
` It cannot be passed down.`
);
}

return (
`\`${fn}\` is a function created with React Hook "useEffectEvent", and can only be called from ` +
'Effects and Effect Events in the same component.' +
Expand Down Expand Up @@ -772,6 +780,22 @@ const rule = {
// comparison later when we exit
lastEffect = node;
}

// Specifically disallow <Child onClick={useEffectEvent(...)} /> because this
// case can't be caught by `recordAllUseEffectEventFunctions` as it isn't assigned to a variable
if (
isUseEffectEventIdentifier(nodeWithoutNamespace) &&
node.parent?.type !== 'VariableDeclarator' &&
// like in other hooks, calling useEffectEvent at component's top level without assignment is valid
node.parent?.type !== 'ExpressionStatement'
) {
const message = useEffectEventError(null, false);

context.report({
node,
message,
});
}
},

Identifier(node) {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-devtools-shared/src/__tests__/store-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1546,7 +1546,7 @@ describe('Store', () => {
▸ <Wrapper>
`);

const deepestedNodeID = agent.getIDForHostInstance(ref.current);
const deepestedNodeID = agent.getIDForHostInstance(ref.current).id;

await act(() => store.toggleIsCollapsed(deepestedNodeID, false));
expect(store).toMatchInlineSnapshot(`
Expand Down
Loading
Loading