Open cmeeren opened 5 years ago
In Fable.React 5 we've tried too simplify the interfaces as they were translated from the React Typescript definitions because they were quite complicated. Looking at the samples you kindly provided the equivalences seem to be:
CompiledName
to allow for "overloads" as in here.type MenuProps =
| AnchorEl of ReactElement
| [<CompiledName("anchorEl")>] AnchorElType of ReactElementType
Thanks for the quick reply!
What is actually ReactElement
and ReactElementType
? In this context, what is the usage difference between them in F# for such a props API? What is possible with one that the other does not allow for?
Also, ReactElementType
is generic, but I have no idea what props type to supply because none of the three previous types are generic. Do you have any idea? Does it make sense to supply obj
?
ReactElement
are instances of React elements, that is, nodes in the Virtual DOM. ReactElementType
are constructors for such elements (basically the components, although the word "component" is usually associated with classes). You can build an element using ReactElementType.create
, but most of the times you will use other helpers.
Again, this is a simplification and you may find different wording/concepts when checking React documentation or tutorials.
It's true that the generic makes it difficult to create a prop accepting any kind of ReactElementType
, so I just added a non generic version in Fable.React 5.1.0. Now you can do:
// In fable-material-ui
type MaterialProp =
| Component of ReactElementType
..
// Usage
let view (props: {| title: string |}) =
h1 [] [str props.title]
let menuProps =
[ Component (ReactElementType.ofFunction view) ]
Thanks! Great to have the non-generic one.
Given a component from a 3rd party library, how would I get a ReactElementType
of that?
@cmeeren You could just use something like:
let inline bigCalendar (props : BigCalendarProps list) : ReactElement =
ofImport "default" "react-big-calendar" (JsInterop.keyValueList CaseRules.LowerFirst props) []
This is what I use in all my bindings and it works. I am not sure why you would need to call ReactElementType
interface yourself. This interface is a really low level thing and most of the timùe you should be able to not use it I think.
@MangelMaxime For an example, check the MUI Input API, specifically the inputComponent
prop. An example usage is given in Text Fields -> Formatted Inputs. Expand the code for that section and search for inputComponent
. You can see that it isn't passed an instance (which AFAIK would be ReactElement
), but rather the component itself (dunno if that was the correct term). The most important code is below:
function TextMaskCustom(props) {
... // component implementation
}
...
class FormattedInputs extends React.Component {
...
render() {
...
return (
...
<Input
...
inputComponent={TextMaskCustom}
/>
...
}
}
TextMaskCustom
is a functional component, but I would guess (I might be wrong) that inputComponent
works the same way with class components too.
Are you saying I still don't need ReactElementType
for the inputComponent
prop?
@cmeeren Ah this is the first time I this kind of code. Then I don't know sorry 😅
React is really cool but sometimes it's really too permissive. I mean there are so many ways and hacks possible to write a component. ^^
Just import it as ReactElementType
(with props typed or not depending on your needs):
// Check the documentation of the component to know if you should import the default or a named member
// See https://fable.io/docs/interacting.html#importing-javascript-code
let BigCalendar: ReactElementType<BigCalendarProps> = importDefault "react-big-calendar"
I'm currently making a PR to update Fable.MaterialUI to Fable.Core 3 and Fable.React 5. The API makes use of
ReactNode
,ReactType
, andReactInstance
, none of which are available any longer.Should
ReactElement
be used instead for all of these?If you need more context to answer this question, here are examples in the (original) MaterialUI documentation where the three types are used in the current bindings:
ReactNode
:checkedIcon
action
,avatar
,subheader
,title
primary
andsecondary
ReactType
:component
inputComponent
IconComponent
ReactInstance
:anchorEl
container