@samitouri / QOS-React / commits / 89064fe68d

Adds displayName to EventComponent and EventTarget (#15268)

* Adds displayName to EventComponent and EventTarget

Dominic Gannaway committed Apr 3, 2019 at 12:24 UTC 89064fe68d1f26da78c541a9c64ee093322b9766
10 files changed +183 -1
packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js
+1
@@ -21,6 +21,7 @@ function createReactEventComponent(targetEventTypes, handleEvent) {
21
22 return {
23 $$typeof: Symbol.for('react.event_component'),
24 + displayName: 'TestEventComponent',
25 props: null,
26 responder: testEventResponder,
27 };
packages/react-events/src/Drag.js
+1
@@ -211,6 +211,7 @@ const DragResponder = {
211
212 export default {
213 $$typeof: REACT_EVENT_COMPONENT_TYPE,
214 + displayName: 'Drag',
215 props: null,
216 responder: DragResponder,
217 };
packages/react-events/src/Focus.js
+1
@@ -122,6 +122,7 @@ const FocusResponder = {
122
123 export default {
124 $$typeof: REACT_EVENT_COMPONENT_TYPE,
125 + displayName: 'Focus',
126 props: null,
127 responder: FocusResponder,
128 };
packages/react-events/src/Hover.js
+1
@@ -204,6 +204,7 @@ const HoverResponder = {
204
205 export default {
206 $$typeof: REACT_EVENT_COMPONENT_TYPE,
207 + displayName: 'Hover',
208 props: null,
209 responder: HoverResponder,
210 };
packages/react-events/src/Press.js
+1
@@ -395,6 +395,7 @@ const PressResponder = {
395
396 export default {
397 $$typeof: REACT_EVENT_COMPONENT_TYPE,
398 + displayName: 'Press',
399 props: null,
400 responder: PressResponder,
401 };
packages/react-events/src/Swipe.js
+1
@@ -239,6 +239,7 @@ const SwipeResponder = {
239
240 export default {
241 $$typeof: REACT_EVENT_COMPONENT_TYPE,
242 + displayName: 'Swipe',
243 props: null,
244 responder: SwipeResponder,
245 };
packages/react-events/src/__tests__/Press-test.internal.js
+4
@@ -394,4 +394,8 @@ describe('Event responder: Press', () => {
394 expect(events).toEqual(['keydown', 'inner: onPress', 'outer: onPress']);
395 });
396 });
397 +
398 + it('expect displayName to show up for event component', () => {
399 + expect(Press.displayName).toBe('Press');
400 + });
401 });
packages/react-reconciler/src/__tests__/ReactFiberEvents-test-internal.js
+148 -1
@@ -29,6 +29,7 @@ const noOpResponder = {
29 function createReactEventComponent() {
30 return {
31 $$typeof: ReactSymbols.REACT_EVENT_COMPONENT_TYPE,
32 + displayName: 'TestEventComponent',
33 props: null,
34 responder: noOpResponder,
35 };
@@ -37,6 +38,7 @@ function createReactEventComponent() {
38 function createReactEventTarget() {
39 return {
40 $$typeof: ReactSymbols.REACT_EVENT_TARGET_TYPE,
41 + displayName: 'TestEventTarget',
42 type: Symbol.for('react.event_target.test'),
43 };
44 }
@@ -392,6 +394,54 @@ describe('ReactFiberEvents', () => {
394 'Warning: validateDOMNesting: React event targets must not have event components as children.',
395 );
396 });
397 +
398 + it('should error with a component stack contains the names of the event components and event targets', () => {
399 + let componentStackMessage;
400 +
401 + function ErrorComponent() {
402 + throw new Error('Failed!');
403 + }
404 +
405 + const Test = () => (
406 + <EventComponent>
407 + <EventTarget>
408 + <span>
409 + <ErrorComponent />
410 + </span>
411 + </EventTarget>
412 + </EventComponent>
413 + );
414 +
415 + class Wrapper extends React.Component {
416 + state = {
417 + error: null,
418 + };
419 +
420 + componentDidCatch(error, errMessage) {
421 + componentStackMessage = errMessage.componentStack;
422 + this.setState({
423 + error,
424 + });
425 + }
426 +
427 + render() {
428 + if (this.state.error) {
429 + return null;
430 + }
431 + return <Test />;
432 + }
433 + }
434 +
435 + ReactNoop.render(<Wrapper />);
436 + expect(Scheduler).toFlushWithoutYielding();
437 +
438 + expect(componentStackMessage.includes('ErrorComponent')).toBe(true);
439 + expect(componentStackMessage.includes('span')).toBe(true);
440 + expect(componentStackMessage.includes('TestEventTarget')).toBe(true);
441 + expect(componentStackMessage.includes('TestEventComponent')).toBe(true);
442 + expect(componentStackMessage.includes('Test')).toBe(true);
443 + expect(componentStackMessage.includes('Wrapper')).toBe(true);
444 + });
445 });
446
447 describe('TestRenderer', () => {
@@ -570,7 +620,7 @@ describe('ReactFiberEvents', () => {
620 error: null,
621 };
622
573 - componentDidCatch(error) {
623 + componentDidCatch(error, errStack) {
624 this.setState({
625 error,
626 });
@@ -734,6 +784,55 @@ describe('ReactFiberEvents', () => {
784 'Warning: validateDOMNesting: React event targets must not have event components as children.',
785 );
786 });
787 +
788 + it('should error with a component stack contains the names of the event components and event targets', () => {
789 + let componentStackMessage;
790 +
791 + function ErrorComponent() {
792 + throw new Error('Failed!');
793 + }
794 +
795 + const Test = () => (
796 + <EventComponent>
797 + <EventTarget>
798 + <span>
799 + <ErrorComponent />
800 + </span>
801 + </EventTarget>
802 + </EventComponent>
803 + );
804 +
805 + class Wrapper extends React.Component {
806 + state = {
807 + error: null,
808 + };
809 +
810 + componentDidCatch(error, errMessage) {
811 + componentStackMessage = errMessage.componentStack;
812 + this.setState({
813 + error,
814 + });
815 + }
816 +
817 + render() {
818 + if (this.state.error) {
819 + return null;
820 + }
821 + return <Test />;
822 + }
823 + }
824 +
825 + const root = ReactTestRenderer.create(null);
826 + root.update(<Wrapper />);
827 + expect(Scheduler).toFlushWithoutYielding();
828 +
829 + expect(componentStackMessage.includes('ErrorComponent')).toBe(true);
830 + expect(componentStackMessage.includes('span')).toBe(true);
831 + expect(componentStackMessage.includes('TestEventTarget')).toBe(true);
832 + expect(componentStackMessage.includes('TestEventComponent')).toBe(true);
833 + expect(componentStackMessage.includes('Test')).toBe(true);
834 + expect(componentStackMessage.includes('Wrapper')).toBe(true);
835 + });
836 });
837
838 describe('ReactDOM', () => {
@@ -1053,6 +1152,54 @@ describe('ReactFiberEvents', () => {
1152 'Warning: validateDOMNesting: React event targets must not have event components as children.',
1153 );
1154 });
1155 +
1156 + it('should error with a component stack contains the names of the event components and event targets', () => {
1157 + let componentStackMessage;
1158 +
1159 + function ErrorComponent() {
1160 + throw new Error('Failed!');
1161 + }
1162 +
1163 + const Test = () => (
1164 + <EventComponent>
1165 + <EventTarget>
1166 + <span>
1167 + <ErrorComponent />
1168 + </span>
1169 + </EventTarget>
1170 + </EventComponent>
1171 + );
1172 +
1173 + class Wrapper extends React.Component {
1174 + state = {
1175 + error: null,
1176 + };
1177 +
1178 + componentDidCatch(error, errMessage) {
1179 + componentStackMessage = errMessage.componentStack;
1180 + this.setState({
1181 + error,
1182 + });
1183 + }
1184 +
1185 + render() {
1186 + if (this.state.error) {
1187 + return null;
1188 + }
1189 + return <Test />;
1190 + }
1191 + }
1192 +
1193 + const container = document.createElement('div');
1194 + ReactDOM.render(<Wrapper />, container);
1195 +
1196 + expect(componentStackMessage.includes('ErrorComponent')).toBe(true);
1197 + expect(componentStackMessage.includes('span')).toBe(true);
1198 + expect(componentStackMessage.includes('TestEventTarget')).toBe(true);
1199 + expect(componentStackMessage.includes('TestEventComponent')).toBe(true);
1200 + expect(componentStackMessage.includes('Test')).toBe(true);
1201 + expect(componentStackMessage.includes('Wrapper')).toBe(true);
1202 + });
1203 });
1204
1205 describe('ReactDOMServer', () => {
packages/shared/ReactTypes.js
+2
@@ -93,11 +93,13 @@ export type ReactEventResponder = {
93
94 export type ReactEventComponent = {|
95 $$typeof: Symbol | number,
96 + displayName?: string,
97 props: null | Object,
98 responder: ReactEventResponder,
99 |};
100
101 export type ReactEventTarget = {|
102 $$typeof: Symbol | number,
103 + displayName?: string,
104 type: Symbol | number,
105 |};
packages/shared/getComponentName.js
+23
@@ -22,8 +22,12 @@ import {
22 REACT_STRICT_MODE_TYPE,
23 REACT_SUSPENSE_TYPE,
24 REACT_LAZY_TYPE,
25 + REACT_EVENT_COMPONENT_TYPE,
26 + REACT_EVENT_TARGET_TYPE,
27 + REACT_EVENT_TARGET_TOUCH_HIT,
28 } from 'shared/ReactSymbols';
29 import {refineResolvedLazyComponent} from 'shared/ReactLazyComponent';
30 +import type {ReactEventComponent, ReactEventTarget} from 'shared/ReactTypes';
31
32 function getWrappedName(
33 outerType: mixed,
@@ -87,6 +91,25 @@ function getComponentName(type: mixed): string | null {
91 if (resolvedThenable) {
92 return getComponentName(resolvedThenable);
93 }
94 + break;
95 + }
96 + case REACT_EVENT_COMPONENT_TYPE: {
97 + const eventComponent = ((type: any): ReactEventComponent);
98 + const displayName = eventComponent.displayName;
99 + if (displayName !== undefined) {
100 + return displayName;
101 + }
102 + break;
103 + }
104 + case REACT_EVENT_TARGET_TYPE: {
105 + const eventTarget = ((type: any): ReactEventTarget);
106 + if (eventTarget.type === REACT_EVENT_TARGET_TOUCH_HIT) {
107 + return 'TouchHitTarget';
108 + }
109 + const displayName = eventTarget.displayName;
110 + if (displayName !== undefined) {
111 + return displayName;
112 + }
113 }
114 }
115 }