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

String is not a valid ComponentType #8380

Closed
danielo515 opened this issue May 20, 2020 · 6 comments
Closed

String is not a valid ComponentType #8380

danielo515 opened this issue May 20, 2020 · 6 comments

Comments

@danielo515
Copy link

Hello
I creating a component that takes a component to render as props. However, it's being impossible for me to type that it can accept both react components and default components (those defined by strings). Flow says that string is not a valid type for ComponentType

// @flow
import * as React from "react";


type Props = {
  component: React.ComponentType<*>
}
  
const Bla = ({component: C }: Props) => <C/>

Bla.defaultProps = {
  component: 'div'
}

const x = <Bla/>

Flow version: 0.125.1

Expected behavior

I expect string to be a valid component

Actual behavior

Only react components can be used

@dsainati1
Copy link
Contributor

dsainati1 commented May 20, 2020

What you are looking for is React.ElementType which is the type of all things that can be inputs to a React element (strings and components).

https://github.com/facebook/flow/blob/master/lib/react.js#L170

@danielo515
Copy link
Author

Hello @dsainati1 thanks for your response.
I read the full documentation about react types before opening the bug, and ElementType is not what I'm looking for. In this case, I don't care about the specific component types, so it may suffice but it is declared as empty, which is not my case. If I try to use it on the example that I provided, this is the error I guet:

9: const Bla = ({component: C }: Props) => <C/>
                                            ^ Cannot create `C` element because props [1] is incompatible with empty [2].
References:
9: const Bla = ({component: C }: Props) => <C/>                                           ^ [1]
[LIB] ..//static/v0.125.1/flowlib/react.js:171:   | React$AbstractComponent<empty, mixed>;
                                                                            ^ [2]

So what I ended up doing is : component: ComponentType<*> | string, which gets the job done, but doesn't feel correct typing.

@danielo515
Copy link
Author

As I said, ElementType is not the proper way, and ComponentType is not working either. What is the recommended way?

@gkz
Copy link
Member

gkz commented May 29, 2020

It doesn't make sense to pass in a component, because by doing <C /> you are passing in a specific set of props (no props), which makes it not possible to ignore what props a component requires.

You should just pass in an element: https://flow.org/try/#0PTAEAEDMBsHsHcBQBLAtgB1gJwC6gFSgCGAzqAEoCmRAxnpFrKqAERbV0sDcivOAnukqgACo3RkAvKADeiUKErRKqSgDscALgoccAOgCyyAB6UAJgFFlqjYgC+80Ihqw1JPACFoRUNIAUMkoq6lqKoHbaYrASAJS+AHyKvF5EemaUkEQArtA4URK+so5BNqEAPGbIAG6gwPEANPa8Lm54xoVlKbXxQA

@danielo515
Copy link
Author

It doesn't make sense to pass in a component

Why does not make sense? it is exactly the same thing high horder components do. I don't want an already instantiated component, I want a component that I will render adding the props that I want. This is a very common react pattern, and it is a key point to customize what certain components use to render themselves (like buttons, where you can specify to render using a Link, an a element etc).
I can accept that this is hard to type on Flow, but you should not say that it doesn't make sense.

@gkz
Copy link
Member

gkz commented May 30, 2020

OK, so what you want is something which accepts a component with specific props, not just arbitrary props, because you need to be able to pass some type of props to it (e.g. href to either the Link or the a.

I don't think there is a way to express that for intrinsic elements (like a), but what you can do is create a simple component to encapsulate their usage, e.g. (props: {href: string}) => <a href={props.href} />, and you can do something like this:

https://flow.org/try/#0PTAEAEDMBsHsHcBQBLAtgB1gJwC6gFSgCGAzqAEoCmRAxnpFrKqAERbV0sDcivOAnukqgACo3QkAPABUAfKAC8oAN6JQoGk0wA7StpwAuChxwA6AMJbYu-dMGVJygBbtIRkjizJtAcwC+sgA0iH486oiQAK7adMjWoABCkTg41jJGyqZZAQAUypoY1nqGoOZ+RmKwEjKyAJQqaqDsOJFY2qCS5qAulJAKLD6wsD7QlKYFLKDAsjyhvEkp1qYAJr1EkdA4lRKKDeoFOsVGOejiJBk9bqAeXr5+9QrykkTdrgrKp1Ukppd+U0EhHi8TTaDygAAeu0kC1S7WmXCmYFWkHWmzIqVAAHIiJjQDgiD5ECCwfwoTD4gcivp3gAZbwAaz+8N4EWisXidO09Lyvwurncnm8-lqRiotDMAFlkODKMsAKKjVDFPZNSgtNodZbIABusgAykxhCiYqToAyNFYbHh4MgcE5iKAzVy8bAVL9JMAtbrZkA

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

3 participants