diff --git a/packages/react-reconciler/src/__tests__/ReactMemo-test.js b/packages/react-reconciler/src/__tests__/ReactMemo-test.js index a7b47621d53e2..8b59d8d104aaf 100644 --- a/packages/react-reconciler/src/__tests__/ReactMemo-test.js +++ b/packages/react-reconciler/src/__tests__/ReactMemo-test.js @@ -657,97 +657,96 @@ describe('memo', () => { }); }); - it('should fall back to showing something meaningful if no displayName or name are present', () => { - const MemoComponent = React.memo(props =>
); - MemoComponent.propTypes = { - required: PropTypes.string.isRequired, - }; - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`Memo`, but its value is `undefined`.', - // There's no component stack in this warning because the inner function is anonymous. - // If we wanted to support this (for the Error frames / source location) - // we could do this by updating ReactComponentStackFrame. - {withoutStack: true}, + it('should skip memo in the stack if neither displayName nor name are present', async () => { + const MemoComponent = React.memo(props => []); + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in p (at **)', ); }); - it('should honor a displayName if set on the inner component in warnings', () => { - function Component(props) { - return
; - } - Component.displayName = 'Inner'; - const MemoComponent = React.memo(Component); - MemoComponent.propTypes = { - required: PropTypes.string.isRequired, - }; - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`Inner`, but its value is `undefined`.\n' + - ' in Inner (at **)', + it('should use the inner function name for the stack', async () => { + const MemoComponent = React.memo(function Inner(props, ref) { + return []; + }); + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in Inner (at **)\n' + + ' in p (at **)', ); }); - it('should honor a displayName if set on the memo wrapper in warnings', () => { - const MemoComponent = React.memo(function Component(props) { - return
; - }); - MemoComponent.displayName = 'Outer'; - MemoComponent.propTypes = { - required: PropTypes.string.isRequired, + it('should use the inner displayName in the stack', async () => { + const fn = (props, ref) => { + return []; }; - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`Outer`, but its value is `undefined`.\n' + - ' in Component (at **)', + fn.displayName = 'Inner'; + const MemoComponent = React.memo(fn); + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in Inner (at **)\n' + + ' in p (at **)', ); }); - it('should pass displayName to an anonymous inner component so it shows up in component stacks', () => { - const MemoComponent = React.memo(props => { - return
; + it('can use the outer displayName in the stack', async () => { + const MemoComponent = React.memo((props, ref) => { + return []; }); - MemoComponent.displayName = 'Memo'; - MemoComponent.propTypes = { - required: PropTypes.string.isRequired, - }; - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`Memo`, but its value is `undefined`.\n' + - ' in Memo (at **)', + MemoComponent.displayName = 'Outer'; + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in Outer (at **)\n' + + ' in p (at **)', ); }); - it('should honor a outer displayName when wrapped component and memo component set displayName at the same time.', () => { - function Component(props) { - return
; - } - Component.displayName = 'Inner'; - - const MemoComponent = React.memo(Component); - MemoComponent.displayName = 'Outer'; - MemoComponent.propTypes = { - required: PropTypes.string.isRequired, + it('should prefer the inner to the outer displayName in the stack', async () => { + const fn = (props, ref) => { + return []; }; - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`Outer`, but its value is `undefined`.\n' + - ' in Inner (at **)', + fn.displayName = 'Inner'; + const MemoComponent = React.memo(fn); + MemoComponent.displayName = 'Outer'; + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in Inner (at **)\n' + + ' in p (at **)', ); }); } diff --git a/packages/react/src/__tests__/forwardRef-test.js b/packages/react/src/__tests__/forwardRef-test.js index 0cfa0031266eb..8a02585a97133 100644 --- a/packages/react/src/__tests__/forwardRef-test.js +++ b/packages/react/src/__tests__/forwardRef-test.js @@ -204,144 +204,98 @@ describe('forwardRef', () => { ); }); - it('should fall back to showing something meaningful if no displayName or name are present', () => { - const Component = props =>
; - - const RefForwardingComponent = React.forwardRef((props, ref) => ( - - )); - - RefForwardingComponent.propTypes = { - optional: PropTypes.string, - required: PropTypes.string.isRequired, - }; - - RefForwardingComponent.defaultProps = { - optional: 'default', - }; - - const ref = React.createRef(); - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`ForwardRef`, but its value is `undefined`.', - // There's no component stack in this warning because the inner function is anonymous. - // If we wanted to support this (for the Error frames / source location) - // we could do this by updating ReactComponentStackFrame. - {withoutStack: true}, + it('should skip forwardRef in the stack if neither displayName nor name are present', async () => { + const RefForwardingComponent = React.forwardRef(function (props, ref) { + return []; + }); + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in p (at **)', ); }); - it('should honor a displayName if set on the forwardRef wrapper in warnings', () => { - const Component = props =>
; - + it('should use the inner function name for the stack', async () => { const RefForwardingComponent = React.forwardRef(function Inner(props, ref) { - ; + return []; }); - RefForwardingComponent.displayName = 'Custom'; - - RefForwardingComponent.propTypes = { - optional: PropTypes.string, - required: PropTypes.string.isRequired, - }; - - RefForwardingComponent.defaultProps = { - optional: 'default', - }; - - const ref = React.createRef(); - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`Custom`, but its value is `undefined`.\n' + - ' in Inner (at **)', + ReactNoop.render( +

+ +

, ); - }); - - it('should pass displayName to an anonymous inner component so it shows up in component stacks', () => { - const Component = props =>
; - - const RefForwardingComponent = React.forwardRef((props, ref) => ( - - )); - RefForwardingComponent.displayName = 'Custom'; - - RefForwardingComponent.propTypes = { - optional: PropTypes.string, - required: PropTypes.string.isRequired, - }; - - RefForwardingComponent.defaultProps = { - optional: 'default', - }; - - const ref = React.createRef(); - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`Custom`, but its value is `undefined`.\n' + - ' in Custom (at **)', + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in Inner (at **)\n' + + ' in p (at **)', ); }); - it('should honor a displayName in stacks if set on the inner function', () => { - const Component = props =>
; - - const inner = (props, ref) => ; - inner.displayName = 'Inner'; - const RefForwardingComponent = React.forwardRef(inner); - - RefForwardingComponent.propTypes = { - optional: PropTypes.string, - required: PropTypes.string.isRequired, + it('should use the inner displayName in the stack', async () => { + const fn = (props, ref) => { + return []; }; - - RefForwardingComponent.defaultProps = { - optional: 'default', - }; - - const ref = React.createRef(); - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`ForwardRef(Inner)`, but its value is `undefined`.\n' + - ' in Inner (at **)', + fn.displayName = 'Inner'; + const RefForwardingComponent = React.forwardRef(fn); + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in Inner (at **)\n' + + ' in p (at **)', ); }); - it('should honor a outer displayName when wrapped component and memo component set displayName at the same time.', () => { - const Component = props =>
; - - const inner = (props, ref) => ; - inner.displayName = 'Inner'; - const RefForwardingComponent = React.forwardRef(inner); + it('can use the outer displayName in the stack', async () => { + const RefForwardingComponent = React.forwardRef((props, ref) => { + return []; + }); RefForwardingComponent.displayName = 'Outer'; + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in Outer (at **)\n' + + ' in p (at **)', + ); + }); - RefForwardingComponent.propTypes = { - optional: PropTypes.string, - required: PropTypes.string.isRequired, - }; - - RefForwardingComponent.defaultProps = { - optional: 'default', + it('should prefer the inner to the outer displayName in the stack', async () => { + const fn = (props, ref) => { + return []; }; - - const ref = React.createRef(); - - expect(() => - ReactNoop.render(), - ).toErrorDev( - 'Warning: Failed prop type: The prop `required` is marked as required in ' + - '`Outer`, but its value is `undefined`.\n' + - ' in Inner (at **)', + fn.displayName = 'Inner'; + const RefForwardingComponent = React.forwardRef(fn); + RefForwardingComponent.displayName = 'Outer'; + ReactNoop.render( +

+ +

, + ); + await expect(async () => { + await waitForAll([]); + }).toErrorDev( + 'Each child in a list should have a unique "key" prop. See https://reactjs.org/link/warning-keys for more information.\n' + + ' in Inner (at **)\n' + + ' in p (at **)', ); });