diff --git a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js index d05585bc2b222..07c6dfa61d4af 100644 --- a/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js +++ b/packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js @@ -5652,6 +5652,60 @@ describe('ReactDOMFizzServer', () => { expect(getVisibleChildren(document.head)).toEqual(hello); }); + it('should accept a single number child', async () => { + // a Single number child + function App() { + return ( + + 4 + + ); + } + + await act(() => { + const {pipe} = renderToPipeableStream(); + pipe(writable); + }); + expect(getVisibleChildren(document.head)).toEqual(4); + + const errors = []; + ReactDOMClient.hydrateRoot(container, , { + onRecoverableError(error) { + errors.push(error.message); + }, + }); + await waitForAll([]); + expect(errors).toEqual([]); + expect(getVisibleChildren(document.head)).toEqual(4); + }); + + it('should accept a single bigint child', async () => { + // a Single number child + function App() { + return ( + + 5n + + ); + } + + await act(() => { + const {pipe} = renderToPipeableStream(); + pipe(writable); + }); + expect(getVisibleChildren(document.head)).toEqual(5n); + + const errors = []; + ReactDOMClient.hydrateRoot(container, , { + onRecoverableError(error) { + errors.push(error.message); + }, + }); + await waitForAll([]); + expect(errors).toEqual([]); + expect(getVisibleChildren(document.head)).toEqual(5n); + }); + it('should accept children array of length 1 containing a string', async () => { // a Single string child function App() { @@ -5694,7 +5748,7 @@ describe('ReactDOMFizzServer', () => { pipe(writable); }); }).toErrorDev([ - 'React expects the `children` prop of tags to be a string, number, or object with a novel `toString` method but found an Array with length 2 instead. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert `children` of <title> tags to a single string value which is why Arrays of length greater than 1 are not supported. When using JSX it can be commong to combine text nodes and value nodes. For example: <title>hello {nameOfUser}. While not immediately apparent, `children` in this case is an Array with length 2. If your `children` prop is using this form try rewriting it using a template string: {`hello ${nameOfUser}`}.', + 'React expects the `children` prop of tags to be a string, number, bigint, or object with a novel `toString` method but found an Array with length 2 instead. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert `children` of <title> tags to a single string value which is why Arrays of length greater than 1 are not supported. When using JSX it can be commong to combine text nodes and value nodes. For example: <title>hello {nameOfUser}. While not immediately apparent, `children` in this case is an Array with length 2. If your `children` prop is using this form try rewriting it using a template string: {`hello ${nameOfUser}`}.', ]); if (gate(flags => flags.enableFloat)) { @@ -5754,7 +5808,63 @@ describe('ReactDOMFizzServer', () => { pipe(writable); }); }).toErrorDev([ - 'React expects the `children` prop of tags to be a string, number, or object with a novel `toString` method but found an object that appears to be a React element which never implements a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags to a single string value which is why rendering React elements is not supported. If the `children` of <title> is a React Component try moving the <title> tag into that component. If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.', + 'React expects the `children` prop of <title> tags to be a string, number, bigint, or object with a novel `toString` method but found an object that appears to be a React element which never implements a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags to a single string value which is why rendering React elements is not supported. If the `children` of <title> is a React Component try moving the <title> tag into that component. If the `children` of <title> is some HTML markup change it to be Text only to be valid HTML.', + ]); + } else { + await expect(async () => { + await act(() => { + const {pipe} = renderToPipeableStream(<App />); + pipe(writable); + }); + }).toErrorDev([ + 'A title element received a React element for children. In the browser title Elements can only have Text Nodes as children. If the children being rendered output more than a single text node in aggregate the browser will display markup and comments as text in the title and hydration will likely fail and fall back to client rendering', + ]); + } + + if (gate(flags => flags.enableFloat)) { + // object titles are toStringed when float is on + expect(getVisibleChildren(document.head)).toEqual( + <title>{'[object Object]'}, + ); + } else { + expect(getVisibleChildren(document.head)).toEqual(hello); + } + + const errors = []; + ReactDOMClient.hydrateRoot(document.head, , { + onRecoverableError(error) { + errors.push(error.message); + }, + }); + await waitForAll([]); + expect(errors).toEqual([]); + if (gate(flags => flags.enableFloat)) { + // object titles are toStringed when float is on + expect(getVisibleChildren(document.head)).toEqual( + {'[object Object]'}, + ); + } else { + expect(getVisibleChildren(document.head)).toEqual(hello); + } + }); + + it('should warn in dev if you pass an object that does not implement toString as a child to ', async () => { + function App() { + return ( + <head> + <title>{{}} + + ); + } + + if (gate(flags => flags.enableFloat)) { + await expect(async () => { + await act(() => { + const {pipe} = renderToPipeableStream(); + pipe(writable); + }); + }).toErrorDev([ + 'React expects the `children` prop of tags to be a string, number, bigint, or object with a novel `toString` method but found an object that does not implement a suitable `toString` method. Browsers treat all child Nodes of <title> tags as Text content and React expects to be able to convert children of <title> tags to a single string value. Using the default `toString` method available on every object is almost certainly an error. Consider whether the `children` of this <title> is an object in error and change it to a string or number value if so. Otherwise implement a `toString` method that React can use to produce a valid <title>.', ]); } else { await expect(async () => {