diff --git a/packages/next/client/head-manager.js b/packages/next/client/head-manager.js index 865f50bc52a88..5eec36503c0ce 100644 --- a/packages/next/client/head-manager.js +++ b/packages/next/client/head-manager.js @@ -95,6 +95,9 @@ function reactElementToDOM({ type, props }) { if (!props.hasOwnProperty(p)) continue if (p === 'children' || p === 'dangerouslySetInnerHTML') continue + // we don't render undefined props to the DOM + if (props[p] === undefined) continue + const attr = DOMAttributeNames[p] || p.toLowerCase() el.setAttribute(attr, props[p]) } diff --git a/test/integration/client-navigation/pages/head.js b/test/integration/client-navigation/pages/head.js index 6b868ec0de995..ae698dc67e70e 100644 --- a/test/integration/client-navigation/pages/head.js +++ b/test/integration/client-navigation/pages/head.js @@ -16,6 +16,9 @@ export default () => ( + {/* this will not render the content prop */} + + {/* allow duplicates for specific tags */} diff --git a/test/integration/client-navigation/test/index.test.js b/test/integration/client-navigation/test/index.test.js index c236e8bd249ac..81aab25d0b341 100644 --- a/test/integration/client-navigation/test/index.test.js +++ b/test/integration/client-navigation/test/index.test.js @@ -1097,6 +1097,15 @@ describe('Client Navigation', () => { await browser.close() }) + it('should handle undefined prop in head client-side', async () => { + const browser = await webdriver(context.appPort, '/head') + const value = await browser.eval( + `document.querySelector('meta[name="empty-content"]').hasAttribute('content')` + ) + + expect(value).toBe(false) + }) + renderingSuite( (p, q) => renderViaHTTP(context.appPort, p, q), (p, q) => fetchViaHTTP(context.appPort, p, q) diff --git a/test/integration/client-navigation/test/rendering.js b/test/integration/client-navigation/test/rendering.js index b7679fbb45796..4bc7ef238d89d 100644 --- a/test/integration/client-navigation/test/rendering.js +++ b/test/integration/client-navigation/test/rendering.js @@ -17,6 +17,14 @@ export default function(render, fetch) { expect(html.includes('My component!')).toBeTruthy() }) + it('should handle undefined prop in head server-side', async () => { + const html = await render('/head') + const $ = cheerio.load(html) + const value = 'content' in $('meta[name="empty-content"]').attr() + + expect(value).toBe(false) + }) + test('renders with fragment syntax', async () => { const html = await render('/fragment-syntax') expect(html.includes('My component!')).toBeTruthy()