@samitouri / QOS-React / commits / d3af2f2a5d

Experimental Event API: add event component mount phase callback (#15480)

Dominic Gannaway committed Apr 24, 2019 at 10:41 UTC d3af2f2a5d7eee1cefb403eee7e67a4f292f5ca8
5 files changed +65 -9
packages/react-dom/src/events/DOMEventResponderSystem.js
+17 -1
@@ -612,7 +612,10 @@ function triggerOwnershipListeners(): void {
612 const instance = listeningInstances[i];
613 const {props, responder, state} = instance;
614 currentInstance = instance;
615 - responder.onOwnershipChange(eventResponderContext, props, state);
615 + const onOwnershipChange = responder.onOwnershipChange;
616 + if (onOwnershipChange !== undefined) {
617 + onOwnershipChange(eventResponderContext, props, state);
618 + }
619 }
620 } finally {
621 currentInstance = previousInstance;
@@ -626,6 +629,19 @@ export function mountEventResponder(
629 if (responder.onOwnershipChange !== undefined) {
630 ownershipChangeListeners.add(eventComponentInstance);
631 }
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 + }
645 }
646
647 export function unmountEventResponder(
packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js
+32 -1
@@ -21,6 +21,7 @@ function createReactEventComponent(
21 onEvent,
22 onEventCapture,
23 onRootEvent,
24 + onMount,
25 onUnmount,
26 onOwnershipChange,
27 stopLocalPropagation,
@@ -32,6 +33,7 @@ function createReactEventComponent(
33 onEvent,
34 onEventCapture,
35 onRootEvent,
36 + onMount,
37 onUnmount,
38 onOwnershipChange,
39 stopLocalPropagation: stopLocalPropagation || false,
@@ -395,6 +397,7 @@ describe('DOMEventResponderSystem', () => {
397 undefined,
398 undefined,
399 undefined,
400 + undefined,
401 true,
402 );
403
@@ -554,6 +557,31 @@ describe('DOMEventResponderSystem', () => {
557 ]);
558 });
559
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 +
585 it('the event responder onUnmount() function should fire', () => {
586 let onUnmountFired = 0;
587
@@ -563,7 +591,8 @@ describe('DOMEventResponderSystem', () => {
591 undefined,
592 undefined,
593 undefined,
566 - (event, context, props, state) => {},
594 + undefined,
595 + undefined,
596 () => {
597 onUnmountFired++;
598 },
@@ -592,6 +621,7 @@ describe('DOMEventResponderSystem', () => {
621 undefined,
622 undefined,
623 undefined,
624 + undefined,
625 (context, props, state) => {
626 counter += state.incrementAmount;
627 },
@@ -623,6 +653,7 @@ describe('DOMEventResponderSystem', () => {
653 undefined,
654 undefined,
655 undefined,
656 + undefined,
657 () => {
658 onOwnershipChangeFired++;
659 },
packages/react-reconciler/src/ReactFiberCommitWork.js
+8 -1
@@ -98,6 +98,7 @@ import {
98 unhideTextInstance,
99 unmountEventComponent,
100 commitEventTarget,
101 + mountEventComponent,
102 } from './ReactFiberHostConfig';
103 import {
104 captureCommitPhaseError,
@@ -595,6 +596,7 @@ function commitLifeCycles(
596 case SuspenseComponent:
597 case IncompleteClassComponent:
598 case EventTarget:
599 + case EventComponent:
600 break;
601 default: {
602 invariant(
@@ -835,7 +837,8 @@ function commitContainer(finishedWork: Fiber) {
837 case ClassComponent:
838 case HostComponent:
839 case HostText:
838 - case EventTarget: {
840 + case EventTarget:
841 + case EventComponent: {
842 return;
843 }
844 case HostRoot:
@@ -1255,6 +1258,10 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1258 case IncompleteClassComponent: {
1259 return;
1260 }
1261 + case EventComponent: {
1262 + mountEventComponent(finishedWork.stateNode);
1263 + return;
1264 + }
1265 default: {
1266 invariant(
1267 false,
packages/react-reconciler/src/ReactFiberCompleteWork.js
+1 -3
@@ -68,7 +68,6 @@ import {
68 createContainerChildSet,
69 appendChildToContainerChildSet,
70 finalizeContainerChildren,
71 - mountEventComponent,
71 updateEventComponent,
72 handleEventTarget,
73 } from './ReactFiberHostConfig';
@@ -813,14 +812,13 @@ function completeWork(
812 responderState = responder.createInitialState(newProps);
813 }
814 eventComponentInstance = workInProgress.stateNode = {
816 - context: null,
815 props: newProps,
816 responder,
817 rootEventTypes: null,
818 rootInstance: rootContainerInstance,
819 state: responderState,
820 };
823 - mountEventComponent(eventComponentInstance);
821 + markUpdate(workInProgress);
822 } else {
823 // Update the props on the event component state node
824 eventComponentInstance.props = newProps;
packages/shared/ReactTypes.js
+7 -3
@@ -108,12 +108,17 @@ export type ReactEventResponder = {
108 props: null | Object,
109 state: null | Object,
110 ) => void,
111 - onUnmount: (
111 + onMount?: (
112 context: ReactResponderContext,
113 props: null | Object,
114 state: null | Object,
115 ) => void,
116 - onOwnershipChange: (
116 + onUnmount?: (
117 + context: ReactResponderContext,
118 + props: null | Object,
119 + state: null | Object,
120 + ) => void,
121 + onOwnershipChange?: (
122 context: ReactResponderContext,
123 props: null | Object,
124 state: null | Object,
@@ -121,7 +126,6 @@ export type ReactEventResponder = {
126 };
127
128 export type ReactEventComponentInstance = {|
124 - context: null | Object,
129 props: null | Object,
130 responder: ReactEventResponder,
131 rootEventTypes: null | Set<string>,