diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js index 2de2daa85d656..914c2d526107c 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -7636,7 +7636,7 @@ if (__EXPERIMENTAL__) { { code: normalizeIndent` function MyComponent({ theme }) { - const onStuff = useEvent(() => { + const onStuff = useEffectEvent(() => { showNotification(theme); }); useEffect(() => { @@ -7652,7 +7652,7 @@ if (__EXPERIMENTAL__) { { code: normalizeIndent` function MyComponent({ theme }) { - const onStuff = useEvent(() => { + const onStuff = useEffectEvent(() => { showNotification(theme); }); useEffect(() => { @@ -7663,14 +7663,14 @@ if (__EXPERIMENTAL__) { errors: [ { message: - 'Functions returned from `useEvent` must not be included in the dependency array. ' + + 'Functions returned from `useEffectEvent` must not be included in the dependency array. ' + 'Remove `onStuff` from the list.', suggestions: [ { desc: 'Remove the dependency `onStuff`', output: normalizeIndent` function MyComponent({ theme }) { - const onStuff = useEvent(() => { + const onStuff = useEffectEvent(() => { showNotification(theme); }); useEffect(() => { diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js index 3148ee877ee49..aa2bcf9846d31 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js @@ -1050,9 +1050,9 @@ if (__EXPERIMENTAL__) { ...tests.valid, { code: normalizeIndent` - // Valid because functions created with useEvent can be called in a useEffect. + // Valid because functions created with useEffectEvent can be called in a useEffect. function MyComponent({ theme }) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); useEffect(() => { @@ -1063,9 +1063,9 @@ if (__EXPERIMENTAL__) { }, { code: normalizeIndent` - // Valid because functions created with useEvent can be called in closures. + // Valid because functions created with useEffectEvent can be called in closures. function MyComponent({ theme }) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); return onClick()}>; @@ -1074,9 +1074,9 @@ if (__EXPERIMENTAL__) { }, { code: normalizeIndent` - // Valid because functions created with useEvent can be called in closures. + // Valid because functions created with useEffectEvent can be called in closures. function MyComponent({ theme }) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); const onClick2 = () => { onClick() }; @@ -1090,13 +1090,13 @@ if (__EXPERIMENTAL__) { }, { code: normalizeIndent` - // Valid because functions created with useEvent can be passed by reference in useEffect - // and useEvent. + // Valid because functions created with useEffectEvent can be passed by reference in useEffect + // and useEffectEvent. function MyComponent({ theme }) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); - const onClick2 = useEvent(() => { + const onClick2 = useEffectEvent(() => { debounce(onClick); }); useEffect(() => { @@ -1110,7 +1110,7 @@ if (__EXPERIMENTAL__) { { code: normalizeIndent` const MyComponent = ({theme}) => { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); return onClick()}>; @@ -1121,10 +1121,10 @@ if (__EXPERIMENTAL__) { code: normalizeIndent` function MyComponent({ theme }) { const notificationService = useNotifications(); - const showNotification = useEvent((text) => { + const showNotification = useEffectEvent((text) => { notificationService.notify(theme, text); }); - const onClick = useEvent((text) => { + const onClick = useEffectEvent((text) => { showNotification(text); }); return onClick(text)} /> @@ -1137,7 +1137,7 @@ if (__EXPERIMENTAL__) { useEffect(() => { onClick(); }); - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); } @@ -1188,64 +1188,64 @@ if (__EXPERIMENTAL__) { { code: normalizeIndent` function MyComponent({ theme }) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); return ; } `, - errors: [useEventError('onClick')], + errors: [useEffectEventError('onClick')], }, { code: normalizeIndent` // This should error even though it shares an identifier name with the below function MyComponent({theme}) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme) }); return } - // The useEvent function shares an identifier name with the above + // The useEffectEvent function shares an identifier name with the above function MyOtherComponent({theme}) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme) }); return onClick()} /> } `, - errors: [{...useEventError('onClick'), line: 7}], + errors: [{...useEffectEventError('onClick'), line: 7}], }, { code: normalizeIndent` const MyComponent = ({ theme }) => { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); return ; } `, - errors: [useEventError('onClick')], + errors: [useEffectEventError('onClick')], }, { code: normalizeIndent` // Invalid because onClick is being aliased to foo but not invoked function MyComponent({ theme }) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(theme); }); let foo = onClick; return } `, - errors: [{...useEventError('onClick'), line: 7}], + errors: [{...useEffectEventError('onClick'), line: 7}], }, { code: normalizeIndent` // Should error because it's being passed down to JSX, although it's been referenced once // in an effect function MyComponent({ theme }) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { showNotification(them); }); useEffect(() => { @@ -1254,7 +1254,7 @@ if (__EXPERIMENTAL__) { return } `, - errors: [useEventError('onClick')], + errors: [useEffectEventError('onClick')], }, { code: normalizeIndent` @@ -1360,10 +1360,10 @@ function classError(hook) { }; } -function useEventError(fn) { +function useEffectEventError(fn) { return { message: - `\`${fn}\` is a function created with React Hook "useEvent", and can only be called from ` + + `\`${fn}\` is a function created with React Hook "useEffectEvent", and can only be called from ` + 'the same component. They cannot be assigned to variables or passed down.', }; } diff --git a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js index 0885d268367f8..fd5bcd1c95ab3 100644 --- a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js +++ b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js @@ -74,7 +74,7 @@ export default { const stateVariables = new WeakSet(); const stableKnownValueCache = new WeakMap(); const functionWithoutCapturedValueCache = new WeakMap(); - const useEventVariables = new WeakSet(); + const useEffectEventVariables = new WeakSet(); function memoizeWithWeakMap(fn, map) { return function(arg) { if (map.has(arg)) { @@ -158,7 +158,7 @@ export default { // ^^^ true for this reference // const ref = useRef() // ^^^ true for this reference - // const onStuff = useEvent(() => {}) + // const onStuff = useEffectEvent(() => {}) // ^^^ true for this reference // False for everything else. function isStableKnownHookValue(resolved) { @@ -226,13 +226,16 @@ export default { if (name === 'useRef' && id.type === 'Identifier') { // useRef() return value is stable. return true; - } else if (isUseEventIdentifier(callee) && id.type === 'Identifier') { + } else if ( + isUseEffectEventIdentifier(callee) && + id.type === 'Identifier' + ) { for (const ref of resolved.references) { if (ref !== id) { - useEventVariables.add(ref.identifier); + useEffectEventVariables.add(ref.identifier); } } - // useEvent() return value is always unstable. + // useEffectEvent() return value is always unstable. return true; } else if (name === 'useState' || name === 'useReducer') { // Only consider second value in initializing tuple stable. @@ -645,11 +648,11 @@ export default { }); return; } - if (useEventVariables.has(declaredDependencyNode)) { + if (useEffectEventVariables.has(declaredDependencyNode)) { reportProblem({ node: declaredDependencyNode, message: - 'Functions returned from `useEvent` must not be included in the dependency array. ' + + 'Functions returned from `useEffectEvent` must not be included in the dependency array. ' + `Remove \`${context.getSource( declaredDependencyNode, )}\` from the list.`, @@ -1851,9 +1854,9 @@ function isAncestorNodeOf(a, b) { return a.range[0] <= b.range[0] && a.range[1] >= b.range[1]; } -function isUseEventIdentifier(node) { +function isUseEffectEventIdentifier(node) { if (__EXPERIMENTAL__) { - return node.type === 'Identifier' && node.name === 'useEvent'; + return node.type === 'Identifier' && node.name === 'useEffectEvent'; } return false; } diff --git a/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js b/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js index 9c915b775a418..ded525e08545f 100644 --- a/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js +++ b/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js @@ -103,9 +103,9 @@ function isInsideComponentOrHook(node) { return false; } -function isUseEventIdentifier(node) { +function isUseEffectEventIdentifier(node) { if (__EXPERIMENTAL__) { - return node.type === 'Identifier' && node.name === 'useEvent'; + return node.type === 'Identifier' && node.name === 'useEffectEvent'; } return false; } @@ -130,12 +130,12 @@ export default { let lastEffect = null; const codePathReactHooksMapStack = []; const codePathSegmentStack = []; - const useEventFunctions = new WeakSet(); + const useEffectEventFunctions = new WeakSet(); - // For a given scope, iterate through the references and add all useEvent definitions. We can - // do this in non-Program nodes because we can rely on the assumption that useEvent functions + // For a given scope, iterate through the references and add all useEffectEvent definitions. We can + // do this in non-Program nodes because we can rely on the assumption that useEffectEvent functions // can only be declared within a component or hook at its top level. - function recordAllUseEventFunctions(scope) { + function recordAllUseEffectEventFunctions(scope) { for (const reference of scope.references) { const parent = reference.identifier.parent; if ( @@ -143,11 +143,11 @@ export default { parent.init && parent.init.type === 'CallExpression' && parent.init.callee && - isUseEventIdentifier(parent.init.callee) + isUseEffectEventIdentifier(parent.init.callee) ) { for (const ref of reference.resolved.references) { if (ref !== reference) { - useEventFunctions.add(ref.identifier); + useEffectEventFunctions.add(ref.identifier); } } } @@ -571,12 +571,12 @@ export default { reactHooks.push(node.callee); } - // useEvent: useEvent functions can be passed by reference within useEffect as well as in - // another useEvent + // useEffectEvent: useEffectEvent functions can be passed by reference within useEffect as well as in + // another useEffectEvent if ( node.callee.type === 'Identifier' && (node.callee.name === 'useEffect' || - isUseEventIdentifier(node.callee)) && + isUseEffectEventIdentifier(node.callee)) && node.arguments.length > 0 ) { // Denote that we have traversed into a useEffect call, and stash the CallExpr for @@ -586,11 +586,11 @@ export default { }, Identifier(node) { - // This identifier resolves to a useEvent function, but isn't being referenced in an + // This identifier resolves to a useEffectEvent function, but isn't being referenced in an // effect or another event function. It isn't being called either. if ( lastEffect == null && - useEventFunctions.has(node) && + useEffectEventFunctions.has(node) && node.parent.type !== 'CallExpression' ) { context.report({ @@ -598,7 +598,7 @@ export default { message: `\`${context.getSource( node, - )}\` is a function created with React Hook "useEvent", and can only be called from ` + + )}\` is a function created with React Hook "useEffectEvent", and can only be called from ` + 'the same component. They cannot be assigned to variables or passed down.', }); } @@ -611,16 +611,16 @@ export default { }, FunctionDeclaration(node) { - // function MyComponent() { const onClick = useEvent(...) } + // function MyComponent() { const onClick = useEffectEvent(...) } if (isInsideComponentOrHook(node)) { - recordAllUseEventFunctions(context.getScope()); + recordAllUseEffectEventFunctions(context.getScope()); } }, ArrowFunctionExpression(node) { - // const MyComponent = () => { const onClick = useEvent(...) } + // const MyComponent = () => { const onClick = useEffectEvent(...) } if (isInsideComponentOrHook(node)) { - recordAllUseEventFunctions(context.getScope()); + recordAllUseEffectEventFunctions(context.getScope()); } }, }; diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js index 79455a7225df8..e314cbae13d1f 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js @@ -5459,13 +5459,13 @@ describe('ReactDOMFizzServer', () => { }); }); - describe('useEvent', () => { - // @gate enableUseEventHook - it('can server render a component with useEvent', async () => { + describe('useEffectEvent', () => { + // @gate enableUseEffectEventHook + it('can server render a component with useEffectEvent', async () => { const ref = React.createRef(); function App() { const [count, setCount] = React.useState(0); - const onClick = React.experimental_useEvent(() => { + const onClick = React.experimental_useEffectEvent(() => { setCount(c => c + 1); }); return ( @@ -5491,11 +5491,11 @@ describe('ReactDOMFizzServer', () => { expect(getVisibleChildren(container)).toEqual(); }); - // @gate enableUseEventHook - it('throws if useEvent is called during a server render', async () => { + // @gate enableUseEffectEventHook + it('throws if useEffectEvent is called during a server render', async () => { const logs = []; function App() { - const onRender = React.experimental_useEvent(() => { + const onRender = React.experimental_useEffectEvent(() => { logs.push('rendered'); }); onRender(); @@ -5518,16 +5518,16 @@ describe('ReactDOMFizzServer', () => { } expect(logs).toEqual([]); expect(caughtError.message).toContain( - "A function wrapped in useEvent can't be called during rendering.", + "A function wrapped in useEffectEvent can't be called during rendering.", ); expect(reportedServerErrors).toEqual([caughtError]); }); - // @gate enableUseEventHook - it('does not guarantee useEvent return values during server rendering are distinct', async () => { + // @gate enableUseEffectEventHook + it('does not guarantee useEffectEvent return values during server rendering are distinct', async () => { function App() { - const onClick1 = React.experimental_useEvent(() => {}); - const onClick2 = React.experimental_useEvent(() => {}); + const onClick1 = React.experimental_useEffectEvent(() => {}); + const onClick2 = React.experimental_useEffectEvent(() => {}); if (onClick1 === onClick2) { return
; } else { diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index eec6e1eb0142f..363e6408711cf 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -50,7 +50,7 @@ import { enableUpdaterTracking, enableCache, enableTransitionTracing, - enableUseEventHook, + enableUseEffectEventHook, enableFloat, enableLegacyHidden, enableHostSingletons, @@ -454,9 +454,9 @@ function commitBeforeMutationEffectsOnFiber(finishedWork: Fiber) { switch (finishedWork.tag) { case FunctionComponent: { - if (enableUseEventHook) { + if (enableUseEffectEventHook) { if ((flags & Update) !== NoFlags) { - commitUseEventMount(finishedWork); + commitUseEffectEventMount(finishedWork); } } break; @@ -706,7 +706,7 @@ function commitHookEffectListMount(flags: HookFlags, finishedWork: Fiber) { } } -function commitUseEventMount(finishedWork: Fiber) { +function commitUseEffectEventMount(finishedWork: Fiber) { const updateQueue: FunctionComponentUpdateQueue | null = (finishedWork.updateQueue: any); const eventPayloads = updateQueue !== null ? updateQueue.events : null; if (eventPayloads !== null) { diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index cf3d34f4c4034..eebd50915f31e 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -38,7 +38,7 @@ import { enableTransitionTracing, enableUseHook, enableUseMemoCacheHook, - enableUseEventHook, + enableUseEffectEventHook, enableLegacyCache, debugRenderPhaseSideEffectsForStrictMode, } from 'shared/ReactFeatureFlags'; @@ -2051,7 +2051,7 @@ function updateEffect( updateEffectImpl(PassiveEffect, HookPassive, create, deps); } -function useEventImpl) => Return>( +function useEffectEventImpl) => Return>( payload: EventFunctionPayload, ) { currentlyRenderingFiber.flags |= UpdateEffect; @@ -2080,7 +2080,7 @@ function mountEvent) => Return>( return function eventFn() { if (isInvalidExecutionContextForEventFunction()) { throw new Error( - "A function wrapped in useEvent can't be called during rendering.", + "A function wrapped in useEffectEvent can't be called during rendering.", ); } return ref.impl.apply(undefined, arguments); @@ -2092,12 +2092,12 @@ function updateEvent) => Return>( ): F { const hook = updateWorkInProgressHook(); const ref = hook.memoizedState; - useEventImpl({ref, nextImpl: callback}); + useEffectEventImpl({ref, nextImpl: callback}); // $FlowIgnore[incompatible-return] return function eventFn() { if (isInvalidExecutionContextForEventFunction()) { throw new Error( - "A function wrapped in useEvent can't be called during rendering.", + "A function wrapped in useEffectEvent can't be called during rendering.", ); } return ref.impl.apply(undefined, arguments); @@ -2780,8 +2780,8 @@ if (enableUseHook) { if (enableUseMemoCacheHook) { (ContextOnlyDispatcher: Dispatcher).useMemoCache = throwInvalidHookError; } -if (enableUseEventHook) { - (ContextOnlyDispatcher: Dispatcher).useEvent = throwInvalidHookError; +if (enableUseEffectEventHook) { + (ContextOnlyDispatcher: Dispatcher).useEffectEvent = throwInvalidHookError; } const HooksDispatcherOnMount: Dispatcher = { @@ -2814,8 +2814,8 @@ if (enableUseHook) { if (enableUseMemoCacheHook) { (HooksDispatcherOnMount: Dispatcher).useMemoCache = useMemoCache; } -if (enableUseEventHook) { - (HooksDispatcherOnMount: Dispatcher).useEvent = mountEvent; +if (enableUseEffectEventHook) { + (HooksDispatcherOnMount: Dispatcher).useEffectEvent = mountEvent; } const HooksDispatcherOnUpdate: Dispatcher = { readContext, @@ -2846,8 +2846,8 @@ if (enableUseMemoCacheHook) { if (enableUseHook) { (HooksDispatcherOnUpdate: Dispatcher).use = use; } -if (enableUseEventHook) { - (HooksDispatcherOnUpdate: Dispatcher).useEvent = updateEvent; +if (enableUseEffectEventHook) { + (HooksDispatcherOnUpdate: Dispatcher).useEffectEvent = updateEvent; } const HooksDispatcherOnRerender: Dispatcher = { @@ -2879,8 +2879,8 @@ if (enableUseHook) { if (enableUseMemoCacheHook) { (HooksDispatcherOnRerender: Dispatcher).useMemoCache = useMemoCache; } -if (enableUseEventHook) { - (HooksDispatcherOnRerender: Dispatcher).useEvent = updateEvent; +if (enableUseEffectEventHook) { + (HooksDispatcherOnRerender: Dispatcher).useEffectEvent = updateEvent; } let HooksDispatcherOnMountInDEV: Dispatcher | null = null; @@ -3059,13 +3059,13 @@ if (__DEV__) { if (enableUseMemoCacheHook) { (HooksDispatcherOnMountInDEV: Dispatcher).useMemoCache = useMemoCache; } - if (enableUseEventHook) { - (HooksDispatcherOnMountInDEV: Dispatcher).useEvent = function useEvent< + if (enableUseEffectEventHook) { + (HooksDispatcherOnMountInDEV: Dispatcher).useEffectEvent = function useEffectEvent< Args, Return, F: (...Array) => Return, >(callback: F): F { - currentHookNameInDev = 'useEvent'; + currentHookNameInDev = 'useEffectEvent'; mountHookTypesDev(); return mountEvent(callback); }; @@ -3214,13 +3214,13 @@ if (__DEV__) { if (enableUseMemoCacheHook) { (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useMemoCache = useMemoCache; } - if (enableUseEventHook) { - (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useEvent = function useEvent< + if (enableUseEffectEventHook) { + (HooksDispatcherOnMountWithHookTypesInDEV: Dispatcher).useEffectEvent = function useEffectEvent< Args, Return, F: (...Array) => Return, >(callback: F): F { - currentHookNameInDev = 'useEvent'; + currentHookNameInDev = 'useEffectEvent'; updateHookTypesDev(); return mountEvent(callback); }; @@ -3369,13 +3369,13 @@ if (__DEV__) { if (enableUseMemoCacheHook) { (HooksDispatcherOnUpdateInDEV: Dispatcher).useMemoCache = useMemoCache; } - if (enableUseEventHook) { - (HooksDispatcherOnUpdateInDEV: Dispatcher).useEvent = function useEvent< + if (enableUseEffectEventHook) { + (HooksDispatcherOnUpdateInDEV: Dispatcher).useEffectEvent = function useEffectEvent< Args, Return, F: (...Array) => Return, >(callback: F): F { - currentHookNameInDev = 'useEvent'; + currentHookNameInDev = 'useEffectEvent'; updateHookTypesDev(); return updateEvent(callback); }; @@ -3525,13 +3525,13 @@ if (__DEV__) { if (enableUseMemoCacheHook) { (HooksDispatcherOnRerenderInDEV: Dispatcher).useMemoCache = useMemoCache; } - if (enableUseEventHook) { - (HooksDispatcherOnRerenderInDEV: Dispatcher).useEvent = function useEvent< + if (enableUseEffectEventHook) { + (HooksDispatcherOnRerenderInDEV: Dispatcher).useEffectEvent = function useEffectEvent< Args, Return, F: (...Array) => Return, >(callback: F): F { - currentHookNameInDev = 'useEvent'; + currentHookNameInDev = 'useEffectEvent'; updateHookTypesDev(); return updateEvent(callback); }; @@ -3707,13 +3707,13 @@ if (__DEV__) { return useMemoCache(size); }; } - if (enableUseEventHook) { - (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useEvent = function useEvent< + if (enableUseEffectEventHook) { + (InvalidNestedHooksDispatcherOnMountInDEV: Dispatcher).useEffectEvent = function useEffectEvent< Args, Return, F: (...Array) => Return, >(callback: F): F { - currentHookNameInDev = 'useEvent'; + currentHookNameInDev = 'useEffectEvent'; warnInvalidHookAccess(); mountHookTypesDev(); return mountEvent(callback); @@ -3890,13 +3890,13 @@ if (__DEV__) { return useMemoCache(size); }; } - if (enableUseEventHook) { - (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useEvent = function useEvent< + if (enableUseEffectEventHook) { + (InvalidNestedHooksDispatcherOnUpdateInDEV: Dispatcher).useEffectEvent = function useEffectEvent< Args, Return, F: (...Array) => Return, >(callback: F): F { - currentHookNameInDev = 'useEvent'; + currentHookNameInDev = 'useEffectEvent'; warnInvalidHookAccess(); updateHookTypesDev(); return updateEvent(callback); @@ -4074,13 +4074,13 @@ if (__DEV__) { return useMemoCache(size); }; } - if (enableUseEventHook) { - (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useEvent = function useEvent< + if (enableUseEffectEventHook) { + (InvalidNestedHooksDispatcherOnRerenderInDEV: Dispatcher).useEffectEvent = function useEffectEvent< Args, Return, F: (...Array) => Return, >(callback: F): F { - currentHookNameInDev = 'useEvent'; + currentHookNameInDev = 'useEffectEvent'; warnInvalidHookAccess(); updateHookTypesDev(); return updateEvent(callback); diff --git a/packages/react-reconciler/src/ReactInternalTypes.js b/packages/react-reconciler/src/ReactInternalTypes.js index 4974f64d9a5cb..f2a1eed3780b6 100644 --- a/packages/react-reconciler/src/ReactInternalTypes.js +++ b/packages/react-reconciler/src/ReactInternalTypes.js @@ -44,7 +44,7 @@ export type HookType = | 'useContext' | 'useRef' | 'useEffect' - | 'useEvent' + | 'useEffectEvent' | 'useInsertionEffect' | 'useLayoutEffect' | 'useCallback' @@ -379,7 +379,9 @@ export type Dispatcher = { create: () => (() => void) | void, deps: Array | void | null, ): void, - useEvent?: ) => Return>(callback: F) => F, + useEffectEvent?: ) => Return>( + callback: F, + ) => F, useInsertionEffect( create: () => (() => void) | void, deps: Array | void | null, diff --git a/packages/react-reconciler/src/__tests__/useEvent-test.js b/packages/react-reconciler/src/__tests__/useEffectEvent-test.js similarity index 92% rename from packages/react-reconciler/src/__tests__/useEvent-test.js rename to packages/react-reconciler/src/__tests__/useEffectEvent-test.js index fecf99679d263..5ebfcf5626843 100644 --- a/packages/react-reconciler/src/__tests__/useEvent-test.js +++ b/packages/react-reconciler/src/__tests__/useEffectEvent-test.js @@ -14,7 +14,7 @@ import {useInsertionEffect} from 'react'; -describe('useEvent', () => { +describe('useEffectEvent', () => { let React; let ReactNoop; let Scheduler; @@ -22,7 +22,7 @@ describe('useEvent', () => { let createContext; let useContext; let useState; - let useEvent; + let useEffectEvent; let useEffect; let useLayoutEffect; let useMemo; @@ -36,7 +36,7 @@ describe('useEvent', () => { createContext = React.createContext; useContext = React.useContext; useState = React.useState; - useEvent = React.experimental_useEvent; + useEffectEvent = React.experimental_useEffectEvent; useEffect = React.useEffect; useLayoutEffect = React.useLayoutEffect; useMemo = React.useMemo; @@ -51,7 +51,7 @@ describe('useEvent', () => { return ; } - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('memoizes basic case correctly', () => { class IncrementButton extends React.PureComponent { increment = () => { @@ -64,7 +64,7 @@ describe('useEvent', () => { function Counter({incrementBy}) { const [count, updateCount] = useState(0); - const onClick = useEvent(() => updateCount(c => c + incrementBy)); + const onClick = useEffectEvent(() => updateCount(c => c + incrementBy)); return ( <> @@ -117,7 +117,7 @@ describe('useEvent', () => { ]); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('can be defined more than once', () => { class IncrementButton extends React.PureComponent { increment = () => { @@ -133,8 +133,8 @@ describe('useEvent', () => { function Counter({incrementBy}) { const [count, updateCount] = useState(0); - const onClick = useEvent(() => updateCount(c => c + incrementBy)); - const onMouseEnter = useEvent(() => { + const onClick = useEffectEvent(() => updateCount(c => c + incrementBy)); + const onMouseEnter = useEffectEvent(() => { updateCount(c => c * incrementBy); }); @@ -173,7 +173,7 @@ describe('useEvent', () => { ]); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('does not preserve `this` in event functions', () => { class GreetButton extends React.PureComponent { greet = () => { @@ -193,7 +193,7 @@ describe('useEvent', () => { }, }; const [greeting, updateGreeting] = useState('Seb says ' + hello); - const onClick = useEvent(person.greet); + const onClick = useEffectEvent(person.greet); return ( <> @@ -222,7 +222,7 @@ describe('useEvent', () => { ]); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('throws when called in render', () => { class IncrementButton extends React.PureComponent { increment = () => { @@ -239,7 +239,7 @@ describe('useEvent', () => { function Counter({incrementBy}) { const [count, updateCount] = useState(0); - const onClick = useEvent(() => updateCount(c => c + incrementBy)); + const onClick = useEffectEvent(() => updateCount(c => c + incrementBy)); return ( <> @@ -251,7 +251,7 @@ describe('useEvent', () => { ReactNoop.render(); expect(Scheduler).toFlushAndThrow( - "A function wrapped in useEvent can't be called during rendering.", + "A function wrapped in useEffectEvent can't be called during rendering.", ); // If something throws, we try one more time synchronously in case the error was @@ -259,7 +259,7 @@ describe('useEvent', () => { expect(Scheduler).toHaveYielded(['Count: 0', 'Count: 0']); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it("useLayoutEffect shouldn't re-fire when event handlers change", () => { class IncrementButton extends React.PureComponent { increment = () => { @@ -272,7 +272,7 @@ describe('useEvent', () => { function Counter({incrementBy}) { const [count, updateCount] = useState(0); - const increment = useEvent(amount => + const increment = useEffectEvent(amount => updateCount(c => c + (amount || incrementBy)), ); @@ -349,7 +349,7 @@ describe('useEvent', () => { ]); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it("useEffect shouldn't re-fire when event handlers change", () => { class IncrementButton extends React.PureComponent { increment = () => { @@ -362,7 +362,7 @@ describe('useEvent', () => { function Counter({incrementBy}) { const [count, updateCount] = useState(0); - const increment = useEvent(amount => + const increment = useEffectEvent(amount => updateCount(c => c + (amount || incrementBy)), ); @@ -438,7 +438,7 @@ describe('useEvent', () => { ]); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('is stable in a custom hook', () => { class IncrementButton extends React.PureComponent { increment = () => { @@ -451,7 +451,7 @@ describe('useEvent', () => { function useCount(incrementBy) { const [count, updateCount] = useState(0); - const increment = useEvent(amount => + const increment = useEffectEvent(amount => updateCount(c => c + (amount || incrementBy)), ); @@ -533,7 +533,7 @@ describe('useEvent', () => { ]); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('is mutated before all other effects', () => { function Counter({value}) { useInsertionEffect(() => { @@ -543,7 +543,7 @@ describe('useEvent', () => { // This is defined after the insertion effect, but it should // update the event fn _before_ the insertion effect fires. - const increment = useEvent(() => { + const increment = useEffectEvent(() => { Scheduler.unstable_yieldValue('Event value: ' + value); }); @@ -557,17 +557,17 @@ describe('useEvent', () => { expect(Scheduler).toHaveYielded(['Effect value: 2', 'Event value: 2']); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it("doesn't provide a stable identity", () => { function Counter({shouldRender, value}) { - const onClick = useEvent(() => { + const onClick = useEffectEvent(() => { Scheduler.unstable_yieldValue( 'onClick, shouldRender=' + shouldRender + ', value=' + value, ); }); // onClick doesn't have a stable function identity so this effect will fire on every render. - // In a real app useEvent functions should *not* be passed as a dependency, this is for + // In a real app useEffectEvent functions should *not* be passed as a dependency, this is for // testing purposes only. useEffect(() => { onClick(); @@ -596,13 +596,13 @@ describe('useEvent', () => { ]); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('event handlers always see the latest committed value', async () => { let committedEventHandler = null; function App({value}) { - const event = useEvent(() => { - return 'Value seen by useEvent: ' + value; + const event = useEffectEvent(() => { + return 'Value seen by useEffectEvent: ' + value; }); // Set up an effect that registers the event handler with an external @@ -619,7 +619,7 @@ describe('useEvent', () => { }, // Note that we've intentionally omitted the event from the dependency // array. But it will still be able to see the latest `value`. This is the - // key feature of useEvent that makes it different from a regular closure. + // key feature of useEffectEvent that makes it different from a regular closure. [], ); return 'Latest rendered value ' + value; @@ -632,7 +632,7 @@ describe('useEvent', () => { }); expect(Scheduler).toHaveYielded(['Commit new event handler']); expect(root).toMatchRenderedOutput('Latest rendered value 1'); - expect(committedEventHandler()).toBe('Value seen by useEvent: 1'); + expect(committedEventHandler()).toBe('Value seen by useEffectEvent: 1'); // Update await act(async () => { @@ -643,10 +643,10 @@ describe('useEvent', () => { expect(Scheduler).toHaveYielded([]); // But the event handler should still be able to see the latest value. expect(root).toMatchRenderedOutput('Latest rendered value 2'); - expect(committedEventHandler()).toBe('Value seen by useEvent: 2'); + expect(committedEventHandler()).toBe('Value seen by useEffectEvent: 2'); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('integration: implements docs chat room example', () => { function createConnection() { let connectedCallback; @@ -675,7 +675,7 @@ describe('useEvent', () => { } function ChatRoom({roomId, theme}) { - const onConnected = useEvent(() => { + const onConnected = useEffectEvent(() => { Scheduler.unstable_yieldValue('Connected! theme: ' + theme); }); @@ -735,7 +735,7 @@ describe('useEvent', () => { expect(Scheduler).toHaveYielded(['Connected! theme: dark']); }); - // @gate enableUseEventHook + // @gate enableUseEffectEventHook it('integration: implements the docs logVisit example', () => { class AddToCartButton extends React.PureComponent { addToCart = () => { @@ -760,10 +760,10 @@ describe('useEvent', () => { function Page({url}) { const {items, updateItems} = useContext(ShoppingCartContext); - const onClick = useEvent(() => updateItems([...items, 1])); + const onClick = useEffectEvent(() => updateItems([...items, 1])); const numberOfItems = items.length; - const onVisit = useEvent(visitedUrl => { + const onVisit = useEffectEvent(visitedUrl => { Scheduler.unstable_yieldValue( 'url: ' + visitedUrl + ', numberOfItems: ' + numberOfItems, ); diff --git a/packages/react-server/src/ReactFizzHooks.js b/packages/react-server/src/ReactFizzHooks.js index b8c1e4c92773b..5a2305eb62899 100644 --- a/packages/react-server/src/ReactFizzHooks.js +++ b/packages/react-server/src/ReactFizzHooks.js @@ -32,7 +32,7 @@ import {makeId} from './ReactServerFormatConfig'; import { enableCache, enableUseHook, - enableUseEventHook, + enableUseEffectEventHook, enableUseMemoCacheHook, } from 'shared/ReactFeatureFlags'; import is from 'shared/objectIs'; @@ -507,17 +507,17 @@ export function useCallback( return useMemo(() => callback, deps); } -function throwOnUseEventCall() { +function throwOnUseEffectEventCall() { throw new Error( - "A function wrapped in useEvent can't be called during rendering.", + "A function wrapped in useEffectEvent can't be called during rendering.", ); } -export function useEvent) => Return>( +export function useEffectEvent) => Return>( callback: F, ): F { // $FlowIgnore[incompatible-return] - return throwOnUseEventCall; + return throwOnUseEffectEventCall; } // TODO Decide on how to implement this hook for server rendering. @@ -651,8 +651,8 @@ export const HooksDispatcher: Dispatcher = { if (enableCache) { HooksDispatcher.useCacheRefresh = useCacheRefresh; } -if (enableUseEventHook) { - HooksDispatcher.useEvent = useEvent; +if (enableUseEffectEventHook) { + HooksDispatcher.useEffectEvent = useEffectEvent; } if (enableUseMemoCacheHook) { HooksDispatcher.useMemoCache = useMemoCache; diff --git a/packages/react/index.classic.fb.js b/packages/react/index.classic.fb.js index 04b905efa759e..48caeb5e13894 100644 --- a/packages/react/index.classic.fb.js +++ b/packages/react/index.classic.fb.js @@ -52,7 +52,7 @@ export { useDeferredValue, useDeferredValue as unstable_useDeferredValue, // TODO: Remove once call sights updated to useDeferredValue useEffect, - experimental_useEvent, + experimental_useEffectEvent, useImperativeHandle, useLayoutEffect, useInsertionEffect, diff --git a/packages/react/index.experimental.js b/packages/react/index.experimental.js index a5b16fcadfc76..876aa3a761758 100644 --- a/packages/react/index.experimental.js +++ b/packages/react/index.experimental.js @@ -44,7 +44,7 @@ export { useDebugValue, useDeferredValue, useEffect, - experimental_useEvent, + experimental_useEffectEvent, useImperativeHandle, useInsertionEffect, useLayoutEffect, diff --git a/packages/react/index.js b/packages/react/index.js index bee9b71e48fed..548c1fe1711ab 100644 --- a/packages/react/index.js +++ b/packages/react/index.js @@ -72,7 +72,7 @@ export { useDebugValue, useDeferredValue, useEffect, - experimental_useEvent, + experimental_useEffectEvent, useImperativeHandle, useInsertionEffect, useLayoutEffect, diff --git a/packages/react/index.modern.fb.js b/packages/react/index.modern.fb.js index 2c446d7bd7f91..68adc9a224641 100644 --- a/packages/react/index.modern.fb.js +++ b/packages/react/index.modern.fb.js @@ -50,7 +50,7 @@ export { useDeferredValue, useDeferredValue as unstable_useDeferredValue, // TODO: Remove once call sights updated to useDeferredValue useEffect, - experimental_useEvent, + experimental_useEffectEvent, useImperativeHandle, useInsertionEffect, useLayoutEffect, diff --git a/packages/react/src/React.js b/packages/react/src/React.js index 399c62f0dc58c..38d40ece0503b 100644 --- a/packages/react/src/React.js +++ b/packages/react/src/React.js @@ -42,7 +42,7 @@ import { useCallback, useContext, useEffect, - useEvent, + useEffectEvent, useImperativeHandle, useDebugValue, useInsertionEffect, @@ -105,7 +105,7 @@ export { useCallback, useContext, useEffect, - useEvent as experimental_useEvent, + useEffectEvent as experimental_useEffectEvent, useImperativeHandle, useDebugValue, useInsertionEffect, diff --git a/packages/react/src/ReactHooks.js b/packages/react/src/ReactHooks.js index a98fdb9c26cb8..716e40b4f7ad8 100644 --- a/packages/react/src/ReactHooks.js +++ b/packages/react/src/ReactHooks.js @@ -235,8 +235,8 @@ export function useMemoCache(size: number): Array { return dispatcher.useMemoCache(size); } -export function useEvent(callback: T): void { +export function useEffectEvent(callback: T): void { const dispatcher = resolveDispatcher(); // $FlowFixMe This is unstable, thus optional - return dispatcher.useEvent(callback); + return dispatcher.useEffectEvent(callback); } diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index d3c128ae77bbe..8fcd13894c33a 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -121,7 +121,7 @@ export const enableUseHook = true; // auto-memoization. export const enableUseMemoCacheHook = __EXPERIMENTAL__; -export const enableUseEventHook = __EXPERIMENTAL__; +export const enableUseEffectEventHook = __EXPERIMENTAL__; // Test in www before enabling in open source. // Enables DOM-server to stream its instruction set as data-attributes diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 8a6f0dc811f90..6d84e76612421 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -54,7 +54,7 @@ export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = true; export const enableUseHook = true; export const enableUseMemoCacheHook = true; -export const enableUseEventHook = false; +export const enableUseEffectEventHook = false; export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true; export const enableClientRenderFallbackOnTextMismatch = true; export const enableComponentStackLocations = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index d2e8863e9128a..9b5c301b7d5ba 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -44,7 +44,7 @@ export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = false; export const enableUseHook = true; export const enableUseMemoCacheHook = false; -export const enableUseEventHook = false; +export const enableUseEffectEventHook = false; export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true; export const enableClientRenderFallbackOnTextMismatch = true; export const enableComponentStackLocations = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index c3a096acef8c1..45561ee4c5fec 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -44,7 +44,7 @@ export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = false; export const enableUseHook = true; export const enableUseMemoCacheHook = false; -export const enableUseEventHook = false; +export const enableUseEffectEventHook = false; export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true; export const enableClientRenderFallbackOnTextMismatch = true; export const enableComponentStackLocations = true; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js index 2f88033de445c..dace39942cf2a 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js @@ -52,7 +52,7 @@ export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = false; export const enableUseHook = true; export const enableUseMemoCacheHook = false; -export const enableUseEventHook = false; +export const enableUseEffectEventHook = false; export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true; export const enableClientRenderFallbackOnTextMismatch = true; export const createRootStrictEffectsByDefault = false; diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index de05d1a8c1d9b..47ed0529927c6 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -44,7 +44,7 @@ export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = false; export const enableUseHook = true; export const enableUseMemoCacheHook = false; -export const enableUseEventHook = false; +export const enableUseEffectEventHook = false; export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true; export const enableClientRenderFallbackOnTextMismatch = true; export const enableComponentStackLocations = true; diff --git a/packages/shared/forks/ReactFeatureFlags.testing.js b/packages/shared/forks/ReactFeatureFlags.testing.js index a239d108dc00f..bfcce69fe7308 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.js @@ -44,7 +44,7 @@ export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = false; export const enableUseHook = true; export const enableUseMemoCacheHook = false; -export const enableUseEventHook = false; +export const enableUseEffectEventHook = false; export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true; export const enableClientRenderFallbackOnTextMismatch = true; export const enableComponentStackLocations = true; diff --git a/packages/shared/forks/ReactFeatureFlags.testing.www.js b/packages/shared/forks/ReactFeatureFlags.testing.www.js index 441b7647bd4d8..e45ef9d1af50c 100644 --- a/packages/shared/forks/ReactFeatureFlags.testing.www.js +++ b/packages/shared/forks/ReactFeatureFlags.testing.www.js @@ -44,7 +44,7 @@ export const enableSuspenseAvoidThisFallbackFizz = false; export const enableCPUSuspense = true; export const enableUseHook = true; export const enableUseMemoCacheHook = false; -export const enableUseEventHook = false; +export const enableUseEffectEventHook = false; export const enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay = true; export const enableClientRenderFallbackOnTextMismatch = true; export const enableComponentStackLocations = true; diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 1a06367d129ef..89fae798d37b2 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -53,7 +53,7 @@ export const enableCPUSuspense = true; export const enableFloat = true; export const enableUseHook = true; export const enableUseMemoCacheHook = true; -export const enableUseEventHook = true; +export const enableUseEffectEventHook = true; export const enableHostSingletons = true; // Logs additional User Timing API marks for use with an experimental profiling tool. diff --git a/scripts/error-codes/codes.json b/scripts/error-codes/codes.json index 022d42e724a85..52fa873e633c2 100644 --- a/scripts/error-codes/codes.json +++ b/scripts/error-codes/codes.json @@ -425,7 +425,7 @@ "437": "the \"precedence\" prop for links to stylesheets expects to receive a string but received something of type \"%s\" instead.", "438": "An unsupported type was passed to use(): %s", "439": "We didn't expect to see a forward reference. This is a bug in the React Server.", - "440": "A function wrapped in useEvent can't be called during rendering.", + "440": "A function wrapped in useEffectEvent can't be called during rendering.", "441": "An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.", "442": "The current renderer does not support Resources. This error is likely caused by a bug in React. Please file an issue.", "443": "acquireResource encountered a resource type it did not expect: \"%s\". this is a bug in React.",