score:0

You can add an isValidElement check before applying React.Children.count as

function getValidChildren(children) {
  return React.Children.toArray(children).filter((child) =>
    React.isValidElement(child)
  ) as React.ReactElement[]
}

function ContextMenuItems({ children }): JSX.Element | null {
   if (!React.Children.count(getValidChildren(children))) return null;
   ...
}

score:0

At the point your parent renders, the children will not have rendered; you only have access to the elements describing them. So, you can check if the element(s) themselves are null or an empty string, as other answers have described. However, if it is a valid element, unfortunately you cannot see if the child's component returns null from its render.

To workaround this, you can manually render it, as @lissettdm has described. Be warned though, it will render children twice; once manually and once normally as a child. And trying to render via type() might often work, but has caveats. This is not ideal.

Hiding via CSS

If it is just that you wish to avoid showing your parent on screen when it renders no children in the DOM; eg. you don't want an empty context menu, then you could consider using simple CSS and targeting your parent with the :empty selector, hiding it that way.

.hidden-if-empty:empty {
  display: none;
}
const ContextMenu = ({ children }) => {
  return <foo className="hidden-if-empty">{children}</foo>
}

Fallback via CSS

If you need to show a fallback, you can use CSS content.

Or alternatively, use the :only-child selector:

.fallback {
  display: none;
}
.fallback-if-empty .fallback:only-child {
  display: block;
}
const ContextMenu = ({ children }) => (
  <foo className="fallback-if-empty">
    {children}
    <bar className="fallback">Nothing to see here!</bar>
  </foo>
);

score:3

you can check if the component has children by reading the children prop, along with the React.Children.count the code would be:

function ContextMenuItems({ children }): JSX.Element | null {
   if (!React.Children.count(children)) return null;
   ...
}

score:3

In addition to the other solutions, if you want to check if a children is an empty string you can do the following test :

!React.isValidElement(children) && children === ""

It helped me to do a helper component that could write a text if the component provided as a children is an empty string:

const EmptyTextHelper = ({ children }: { children?: React.ReactNode }) => !React.isValidElement(children) && children === "" ? (
<span className="italic">No text</span>) : (
<>{children}</>);

score:18

Solution 1:

Get the children type. It will return null if Child component returns null:

const isChildNull = children => {
  return Boolean(children.type()=== null);
};

Solution 2:

Using ReactDOMServer.renderToStaticMarkup. It converts the jsx elements to string. If children returns null then renderToStaticMarkup will return an empty string:

import ReactDOMServer from 'react-dom/server';

const isChildNull = children => {
  return !Boolean(ReactDOMServer.renderToStaticMarkup(children));
};

Usage:

const Child = () => {
  return null;
};
    
const Parent = ({ children }) => {
  const isNull = isChildNull(children);
  if (isNull) {
     return "render null";
  }
  return <div>{children}</div>;
};
    
export default function App() {
   return (
     <Parent>
        <Child />
     </Parent>
   );
}

Working example using solution 1


Related Query

More Query from same tag