6

Say I'm making a wrapper component which should only render itself if some child nodes are passed in:

const Wrapper = ({children}) => {
  if (!children) return null
  return <div>{children}</div>
}

The problem is that children could be a Fragment containing null, or an array of nulls. Or a fragment containing a fragment containing...

<Wrapper>hey</Wrapper> // renders <div>hey</div> 
<Wrapper>{null}</Wrapper> // renders nothing 
<Wrapper>{[null]}</Wrapper> // renders <div/> 
<Wrapper><React.Fragment>{null}</React.Fragment></Wrapper> // renders <div/> 

Is there a canonical way to check for all these conditions?

Tamlyn
  • 22,122
  • 12
  • 111
  • 127

2 Answers2

2

Maybe this is what you're looking for :

import ReactDOMServer from 'react-dom/server';

const Wrapper = ({children}) => {
  const markup = ReactDOMServer.renderToStaticMarkup(children);
  if (!markup.trim()) return null;

  return <div>{children}</div>
}
Mohamed Ramrami
  • 12,026
  • 4
  • 33
  • 49
  • This could work, thanks. I wonder if there are implications of loading `react-dom/server` on the client side. – Tamlyn Sep 30 '19 at 12:59
  • 1
    From the react docs, `ReactDOMServer.renderToStaticMarkup` can be used in both the server and browser. https://reactjs.org/docs/react-dom-server.html#overview – Mohamed Ramrami Sep 30 '19 at 14:28
  • It looked promising, but this will cause any portals in `children` to be rendered – andrew Nov 20 '22 at 05:15
1

No need to check. They simply don't render.

false, null, undefined, and true are valid children. They simply don’t render. These JSX expressions will all render to the same thing:

<div />

<div></div>

<div>{false}</div>

<div>{null}</div>

<div>{undefined}</div>

<div>{true}</div>
Joseph D.
  • 11,804
  • 3
  • 34
  • 67
  • 1
    The children don't render but it's the wrapper I care about (see updated question with examples). – Tamlyn Sep 30 '19 at 13:00