No suitable component definition found for container component
type Props = {
children: React.Element,
renderStatus?: () => React.Element
};
function Test(props: Props, context) {
if (context.show) {
return props.renderStatus ? props.renderStatus() : null;
}
return props.children;
}
Test.contextTypes = {
show: PropTypes.bool
};
export default React.memo(Test)
output
Error: No suitable component definition found.
That's because Test doesn't pass the heuristic used to determine whether a function is a React component or not. A quick workaround would be to use
return <>{props.children}</>;
@danez, any thoughts on extending the heuristic? Test.contextType is a give-away, but it may not always exist. Should we actually add support for marking functions as react components via a tag (i.e. @react or something), to have a simple escape hatch?
There are two problems in this example:
- React.memo() was not supported, will be fixed in #343
- The component does not return jsx as felix mentioned and is therefore not detected as component.
I think adding support for @react is a good last resort. I will try to add propTypes, defaultProps and contextTypes to the detection first.
Similar issue when returning a portal.
Simplified example:
const Dialog = (props) => {
return ReactDOM.createPortal(<MyDialogHere {...props}/>, document.body);
}
Dialog.propTypes = {
/** If only these docs could be detected... */
children: PropTypes.node
}
The fragment workaround does work, but +1 for allowing the presence of propTypes to trigger detection like @danez mentioned.
I'm experiencing the same when returning a portal. Interestingly enough, it works when using a class component instead.
Also ran into this problem with a functional component which returns ReactDOM.createPortal(...). It would be nice to not have to wrap in a fragment.
Similar issue when returning a portal.
Simplified example:
const Dialog = (props) => { return ReactDOM.createPortal(<MyDialogHere {...props}/>, document.body); } Dialog.propTypes = { /** If only these docs could be detected... */ children: PropTypes.node }The fragment workaround does work, but +1 for allowing the presence of
propTypesto trigger detection like @danez mentioned.
I use the fragment workaround but with shorthand fragment <></> does not work only with explicit <React.Fragment> or any other html wrapper like <div>
Useful for "container" like components, similar to the downshift API.
import * as React from 'react'
type Props = {
render: () => React.Element<any>,
}
function MyComponent({ render }: Props) {
return render()
}
export default MyComponent;
I understand that with such case there's not much to rely on to distinguish a component from a function. Maybe the fact that react is imported?
Inside functional component, if createPortal() method is used, be sure NOT to return null in the ternary operator.
Instead of this,
return opened ? ReactDOM.createPortal(renderHTML(), document.body) : null;
use this,
return opened ? ReactDOM.createPortal(renderHTML(), document.body) : <></>;
This solved my problem. :)
To add to the discussion, aside from ReactDOM.createPortal, you can reproduce this bug with other "wrapper" functions as well (using version 5.4.3):
import { Popup } from '/path/to/example/Popup';
let container = <div>Foo Bar</div>;
return Popup.attach(container, 'Hello World'); // Error: No suitable component definition found.
^ Fragment workaround works here too. e.g. return <>{Popup.attach(container, 'Hello World')}</>