diff --git a/debug/src/debug.js b/debug/src/debug.js index 73c9c3dcef..56998711a1 100644 --- a/debug/src/debug.js +++ b/debug/src/debug.js @@ -353,7 +353,13 @@ export function initDebug() { }); } - if (typeof type === 'string' && (isTableElement(type) || type === 'p')) { + if ( + typeof type === 'string' && + (isTableElement(type) || + type === 'p' || + type === 'a' || + type === 'button') + ) { // Avoid false positives when Preact only partially rendered the // HTML tree. Whilst we attempt to include the outer DOM in our // validation, this wouldn't work on the server for @@ -420,6 +426,16 @@ export function initDebug() { `\n\n${getOwnerStack(vnode)}` ); } + } else if (type === 'a' || type === 'button') { + if (getDomChildren(vnode).indexOf(type) !== -1) { + console.error( + `Improper nesting of interactive content. Your <${type}>` + + ` should not have other ${type === 'a' ? 'anchor' : 'button'}` + + ' tags as child-elements.' + + serializeVNode(vnode) + + `\n\n${getOwnerStack(vnode)}` + ); + } } } diff --git a/debug/test/browser/debug.test.js b/debug/test/browser/debug.test.js index b88bd8cb2c..fa318697d8 100644 --- a/debug/test/browser/debug.test.js +++ b/debug/test/browser/debug.test.js @@ -667,6 +667,94 @@ describe('debug', () => { }); }); + describe('button nesting', () => { + it('should not warn on a regular button', () => { + const Button = () => ; + + render( + + ); + + render(; + const Button = () => ( + + ); + + render( + ); + + render( + + ); + + render(, scratch); + expect(console.error).to.not.be.called; + }); + }); + describe('PropTypes', () => { beforeEach(() => { resetPropWarnings();