Skip to content

Commit c2a2d8a

Browse files
authored
Remove useMutationEffect (#14336)
useMutationEffect has problems (namely, refs aren't attached at the time that it runs) and we're not positive it's necessary. useLayoutEffect runs at the same time as componentDidMount/Update so it's sufficient for all existing use cases; it can be used in any case that useEffect happens too late. Until we figure out what we want to do, let's delete it.
1 parent 48f1e5b commit c2a2d8a

File tree

11 files changed

+22
-275
lines changed

11 files changed

+22
-275
lines changed

packages/react-debug-tools/src/ReactDebugHooks.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ function getPrimitiveStackCache(): Map<string, Array<any>> {
5252
Dispatcher.useState(null);
5353
Dispatcher.useReducer((s, a) => s, null);
5454
Dispatcher.useRef(null);
55-
Dispatcher.useMutationEffect(() => {});
5655
Dispatcher.useLayoutEffect(() => {});
5756
Dispatcher.useEffect(() => {});
5857
Dispatcher.useImperativeMethods(undefined, () => null);
@@ -140,18 +139,6 @@ function useRef<T>(initialValue: T): {current: T} {
140139
return ref;
141140
}
142141

143-
function useMutationEffect(
144-
create: () => mixed,
145-
inputs: Array<mixed> | void | null,
146-
): void {
147-
nextHook();
148-
hookLog.push({
149-
primitive: 'MutationEffect',
150-
stackError: new Error(),
151-
value: create,
152-
});
153-
}
154-
155142
function useLayoutEffect(
156143
create: () => mixed,
157144
inputs: Array<mixed> | void | null,
@@ -221,7 +208,6 @@ const Dispatcher = {
221208
useImperativeMethods,
222209
useLayoutEffect,
223210
useMemo,
224-
useMutationEffect,
225211
useReducer,
226212
useRef,
227213
useState,

packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.internal.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ describe('ReactHooksInspection', () => {
129129
return result;
130130
}
131131
function useBaz(value) {
132-
React.useMutationEffect(effect);
132+
React.useLayoutEffect(effect);
133133
let result = useCustom(value);
134134
return result;
135135
}
@@ -176,7 +176,7 @@ describe('ReactHooksInspection', () => {
176176
value: undefined,
177177
subHooks: [
178178
{
179-
name: 'MutationEffect',
179+
name: 'LayoutEffect',
180180
value: effect,
181181
subHooks: [],
182182
},

packages/react-debug-tools/src/__tests__/ReactHooksInspectionIntegration-test.internal.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ describe('ReactHooksInspectionIntergration', () => {
7979
let [state2, dispatch] = React.useReducer((s, a) => a.value, 'b');
8080
let ref = React.useRef('c');
8181

82-
React.useMutationEffect(effect);
8382
React.useLayoutEffect(effect);
8483
React.useEffect(effect);
8584

@@ -117,7 +116,6 @@ describe('ReactHooksInspectionIntergration', () => {
117116
{name: 'State', value: 'a', subHooks: []},
118117
{name: 'Reducer', value: 'b', subHooks: []},
119118
{name: 'Ref', value: 'c', subHooks: []},
120-
{name: 'MutationEffect', value: effect, subHooks: []},
121119
{name: 'LayoutEffect', value: effect, subHooks: []},
122120
{name: 'Effect', value: effect, subHooks: []},
123121
{name: 'ImperativeMethods', value: outsideRef.current, subHooks: []},
@@ -134,7 +132,6 @@ describe('ReactHooksInspectionIntergration', () => {
134132
{name: 'State', value: 'A', subHooks: []},
135133
{name: 'Reducer', value: 'B', subHooks: []},
136134
{name: 'Ref', value: 'C', subHooks: []},
137-
{name: 'MutationEffect', value: effect, subHooks: []},
138135
{name: 'LayoutEffect', value: effect, subHooks: []},
139136
{name: 'Effect', value: effect, subHooks: []},
140137
{name: 'ImperativeMethods', value: outsideRef.current, subHooks: []},

packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.internal.js

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ let useCallback;
2525
let useMemo;
2626
let useRef;
2727
let useImperativeMethods;
28-
let useMutationEffect;
2928
let useLayoutEffect;
3029
let forwardRef;
3130
let yieldedValues;
@@ -50,7 +49,6 @@ function initModules() {
5049
useMemo = React.useMemo;
5150
useRef = React.useRef;
5251
useImperativeMethods = React.useImperativeMethods;
53-
useMutationEffect = React.useMutationEffect;
5452
useLayoutEffect = React.useLayoutEffect;
5553
forwardRef = React.forwardRef;
5654

@@ -551,22 +549,6 @@ describe('ReactDOMServerHooks', () => {
551549
});
552550
});
553551

554-
describe('useMutationEffect', () => {
555-
it('should warn when invoked during render', async () => {
556-
function Counter() {
557-
useMutationEffect(() => {
558-
throw new Error('should not be invoked');
559-
});
560-
561-
return <Text text="Count: 0" />;
562-
}
563-
const domNode = await serverRender(<Counter />, 1);
564-
expect(clearYields()).toEqual(['Count: 0']);
565-
expect(domNode.tagName).toEqual('SPAN');
566-
expect(domNode.textContent).toEqual('Count: 0');
567-
});
568-
});
569-
570552
describe('useLayoutEffect', () => {
571553
it('should warn when invoked during render', async () => {
572554
function Counter() {

packages/react-dom/src/server/ReactPartialRendererHooks.js

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -271,20 +271,6 @@ function useRef<T>(initialValue: T): {current: T} {
271271
}
272272
}
273273

274-
function useMutationEffect(
275-
create: () => mixed,
276-
inputs: Array<mixed> | void | null,
277-
) {
278-
warning(
279-
false,
280-
'useMutationEffect does nothing on the server, because its effect cannot ' +
281-
"be encoded into the server renderer's output format. This will lead " +
282-
'to a mismatch between the initial, non-hydrated UI and the intended ' +
283-
'UI. To avoid this, useMutationEffect should only be used in ' +
284-
'components that render exclusively on the client.',
285-
);
286-
}
287-
288274
export function useLayoutEffect(
289275
create: () => mixed,
290276
inputs: Array<mixed> | void | null,
@@ -358,7 +344,6 @@ export const Dispatcher = {
358344
useReducer,
359345
useRef,
360346
useState,
361-
useMutationEffect,
362347
useLayoutEffect,
363348
// Callbacks are passed as they are in the server environment.
364349
useCallback: identity,

packages/react-reconciler/src/ReactFiberCommitWork.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,8 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
10871087
case ForwardRef:
10881088
case MemoComponent:
10891089
case SimpleMemoComponent: {
1090+
// Note: We currently never use MountMutation, but useLayout uses
1091+
// UnmountMutation.
10901092
commitHookEffectList(UnmountMutation, MountMutation, finishedWork);
10911093
return;
10921094
}
@@ -1101,6 +1103,8 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
11011103
case ForwardRef:
11021104
case MemoComponent:
11031105
case SimpleMemoComponent: {
1106+
// Note: We currently never use MountMutation, but useLayout uses
1107+
// UnmountMutation.
11041108
commitHookEffectList(UnmountMutation, MountMutation, finishedWork);
11051109
return;
11061110
}

packages/react-reconciler/src/ReactFiberDispatcher.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
useImperativeMethods,
1616
useLayoutEffect,
1717
useMemo,
18-
useMutationEffect,
1918
useReducer,
2019
useRef,
2120
useState,
@@ -29,7 +28,6 @@ export const Dispatcher = {
2928
useImperativeMethods,
3029
useLayoutEffect,
3130
useMemo,
32-
useMutationEffect,
3331
useReducer,
3432
useRef,
3533
useState,

packages/react-reconciler/src/ReactFiberHooks.js

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,12 @@ import {NoWork} from './ReactFiberExpirationTime';
1616
import {enableHooks} from 'shared/ReactFeatureFlags';
1717
import {readContext} from './ReactFiberNewContext';
1818
import {
19-
Snapshot as SnapshotEffect,
2019
Update as UpdateEffect,
2120
Passive as PassiveEffect,
2221
} from 'shared/ReactSideEffectTags';
2322
import {
2423
NoEffect as NoHookEffect,
25-
UnmountSnapshot,
2624
UnmountMutation,
27-
MountMutation,
2825
MountLayout,
2926
UnmountPassive,
3027
MountPassive,
@@ -517,18 +514,6 @@ export function useRef<T>(initialValue: T): {current: T} {
517514
return ref;
518515
}
519516

520-
export function useMutationEffect(
521-
create: () => mixed,
522-
inputs: Array<mixed> | void | null,
523-
): void {
524-
useEffectImpl(
525-
SnapshotEffect | UpdateEffect,
526-
UnmountSnapshot | MountMutation,
527-
create,
528-
inputs,
529-
);
530-
}
531-
532517
export function useLayoutEffect(
533518
create: () => mixed,
534519
inputs: Array<mixed> | void | null,
@@ -586,26 +571,21 @@ export function useImperativeMethods<T>(
586571
// TODO: I've implemented this on top of useEffect because it's almost the
587572
// same thing, and it would require an equal amount of code. It doesn't seem
588573
// like a common enough use case to justify the additional size.
589-
useEffectImpl(
590-
UpdateEffect,
591-
UnmountMutation | MountLayout,
592-
() => {
593-
if (typeof ref === 'function') {
594-
const refCallback = ref;
595-
const inst = create();
596-
refCallback(inst);
597-
return () => refCallback(null);
598-
} else if (ref !== null && ref !== undefined) {
599-
const refObject = ref;
600-
const inst = create();
601-
refObject.current = inst;
602-
return () => {
603-
refObject.current = null;
604-
};
605-
}
606-
},
607-
nextInputs,
608-
);
574+
useLayoutEffect(() => {
575+
if (typeof ref === 'function') {
576+
const refCallback = ref;
577+
const inst = create();
578+
refCallback(inst);
579+
return () => refCallback(null);
580+
} else if (ref !== null && ref !== undefined) {
581+
const refObject = ref;
582+
const inst = create();
583+
refObject.current = inst;
584+
return () => {
585+
refObject.current = null;
586+
};
587+
}
588+
}, nextInputs);
609589
}
610590

611591
export function useCallback<T>(

0 commit comments

Comments
 (0)