Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No suitable component definition found for container component #336

Open
m860 opened this issue Mar 15, 2019 · 9 comments
Open

No suitable component definition found for container component #336

m860 opened this issue Mar 15, 2019 · 9 comments

Comments

@m860
Copy link

m860 commented Mar 15, 2019

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.
@fkling
Copy link
Member

fkling commented Mar 19, 2019

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?

@danez
Copy link
Collaborator

danez commented Apr 13, 2019

There are two problems in this example:

  1. React.memo() was not supported, will be fixed in Assume HOC first param is Component not last #343
  2. 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.

@greypants
Copy link

greypants commented May 30, 2019

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.

@cironunes
Copy link

I'm experiencing the same when returning a portal. Interestingly enough, it works when using a class component instead.

@robertwbradford
Copy link

robertwbradford commented Aug 8, 2019

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.

@dastasoft
Copy link

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 use the fragment workaround but with shorthand fragment <></> does not work only with explicit <React.Fragment> or any other html wrapper like <div>

@pascalduez
Copy link

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?

@av1v3k
Copy link

av1v3k commented Apr 15, 2021

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. :)

@neutraali
Copy link

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')}</>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants