Skip to content

Commit d3af2f2

Browse files
authored
Experimental Event API: add event component mount phase callback (facebook#15480)
1 parent ce126fb commit d3af2f2

File tree

5 files changed

+65
-9
lines changed

5 files changed

+65
-9
lines changed

packages/react-dom/src/events/DOMEventResponderSystem.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,10 @@ function triggerOwnershipListeners(): void {
612612
const instance = listeningInstances[i];
613613
const {props, responder, state} = instance;
614614
currentInstance = instance;
615-
responder.onOwnershipChange(eventResponderContext, props, state);
615+
const onOwnershipChange = responder.onOwnershipChange;
616+
if (onOwnershipChange !== undefined) {
617+
onOwnershipChange(eventResponderContext, props, state);
618+
}
616619
}
617620
} finally {
618621
currentInstance = previousInstance;
@@ -626,6 +629,19 @@ export function mountEventResponder(
626629
if (responder.onOwnershipChange !== undefined) {
627630
ownershipChangeListeners.add(eventComponentInstance);
628631
}
632+
const onMount = responder.onMount;
633+
if (onMount !== undefined) {
634+
let {props, state} = eventComponentInstance;
635+
currentEventQueue = createEventQueue();
636+
currentInstance = eventComponentInstance;
637+
try {
638+
onMount(eventResponderContext, props, state);
639+
} finally {
640+
currentEventQueue = null;
641+
currentInstance = null;
642+
currentTimers = null;
643+
}
644+
}
629645
}
630646

631647
export function unmountEventResponder(

packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ function createReactEventComponent(
2121
onEvent,
2222
onEventCapture,
2323
onRootEvent,
24+
onMount,
2425
onUnmount,
2526
onOwnershipChange,
2627
stopLocalPropagation,
@@ -32,6 +33,7 @@ function createReactEventComponent(
3233
onEvent,
3334
onEventCapture,
3435
onRootEvent,
36+
onMount,
3537
onUnmount,
3638
onOwnershipChange,
3739
stopLocalPropagation: stopLocalPropagation || false,
@@ -395,6 +397,7 @@ describe('DOMEventResponderSystem', () => {
395397
undefined,
396398
undefined,
397399
undefined,
400+
undefined,
398401
true,
399402
);
400403

@@ -554,6 +557,31 @@ describe('DOMEventResponderSystem', () => {
554557
]);
555558
});
556559

560+
it('the event responder onMount() function should fire', () => {
561+
let onMountFired = 0;
562+
563+
const EventComponent = createReactEventComponent(
564+
[],
565+
undefined,
566+
undefined,
567+
undefined,
568+
undefined,
569+
undefined,
570+
() => {
571+
onMountFired++;
572+
},
573+
);
574+
575+
const Test = () => (
576+
<EventComponent>
577+
<button />
578+
</EventComponent>
579+
);
580+
581+
ReactDOM.render(<Test />, container);
582+
expect(onMountFired).toEqual(1);
583+
});
584+
557585
it('the event responder onUnmount() function should fire', () => {
558586
let onUnmountFired = 0;
559587

@@ -563,7 +591,8 @@ describe('DOMEventResponderSystem', () => {
563591
undefined,
564592
undefined,
565593
undefined,
566-
(event, context, props, state) => {},
594+
undefined,
595+
undefined,
567596
() => {
568597
onUnmountFired++;
569598
},
@@ -592,6 +621,7 @@ describe('DOMEventResponderSystem', () => {
592621
undefined,
593622
undefined,
594623
undefined,
624+
undefined,
595625
(context, props, state) => {
596626
counter += state.incrementAmount;
597627
},
@@ -623,6 +653,7 @@ describe('DOMEventResponderSystem', () => {
623653
undefined,
624654
undefined,
625655
undefined,
656+
undefined,
626657
() => {
627658
onOwnershipChangeFired++;
628659
},

packages/react-reconciler/src/ReactFiberCommitWork.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import {
9898
unhideTextInstance,
9999
unmountEventComponent,
100100
commitEventTarget,
101+
mountEventComponent,
101102
} from './ReactFiberHostConfig';
102103
import {
103104
captureCommitPhaseError,
@@ -595,6 +596,7 @@ function commitLifeCycles(
595596
case SuspenseComponent:
596597
case IncompleteClassComponent:
597598
case EventTarget:
599+
case EventComponent:
598600
break;
599601
default: {
600602
invariant(
@@ -835,7 +837,8 @@ function commitContainer(finishedWork: Fiber) {
835837
case ClassComponent:
836838
case HostComponent:
837839
case HostText:
838-
case EventTarget: {
840+
case EventTarget:
841+
case EventComponent: {
839842
return;
840843
}
841844
case HostRoot:
@@ -1255,6 +1258,10 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
12551258
case IncompleteClassComponent: {
12561259
return;
12571260
}
1261+
case EventComponent: {
1262+
mountEventComponent(finishedWork.stateNode);
1263+
return;
1264+
}
12581265
default: {
12591266
invariant(
12601267
false,

packages/react-reconciler/src/ReactFiberCompleteWork.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ import {
6868
createContainerChildSet,
6969
appendChildToContainerChildSet,
7070
finalizeContainerChildren,
71-
mountEventComponent,
7271
updateEventComponent,
7372
handleEventTarget,
7473
} from './ReactFiberHostConfig';
@@ -813,14 +812,13 @@ function completeWork(
813812
responderState = responder.createInitialState(newProps);
814813
}
815814
eventComponentInstance = workInProgress.stateNode = {
816-
context: null,
817815
props: newProps,
818816
responder,
819817
rootEventTypes: null,
820818
rootInstance: rootContainerInstance,
821819
state: responderState,
822820
};
823-
mountEventComponent(eventComponentInstance);
821+
markUpdate(workInProgress);
824822
} else {
825823
// Update the props on the event component state node
826824
eventComponentInstance.props = newProps;

packages/shared/ReactTypes.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,24 @@ export type ReactEventResponder = {
108108
props: null | Object,
109109
state: null | Object,
110110
) => void,
111-
onUnmount: (
111+
onMount?: (
112112
context: ReactResponderContext,
113113
props: null | Object,
114114
state: null | Object,
115115
) => void,
116-
onOwnershipChange: (
116+
onUnmount?: (
117+
context: ReactResponderContext,
118+
props: null | Object,
119+
state: null | Object,
120+
) => void,
121+
onOwnershipChange?: (
117122
context: ReactResponderContext,
118123
props: null | Object,
119124
state: null | Object,
120125
) => void,
121126
};
122127

123128
export type ReactEventComponentInstance = {|
124-
context: null | Object,
125129
props: null | Object,
126130
responder: ReactEventResponder,
127131
rootEventTypes: null | Set<string>,

0 commit comments

Comments
 (0)