Using React components
Because Elmish is just a thin layer on top of React, it is quite easy to use non-PureScript React components from the wider ecosystem.
A typical import of a React component consists of three parts:
- A row of props, with optional props denoted via
Opt
. - Actual FFI-import of the component constructor. This import is weakly typed and shouldn’t be exported from the module. Consider it internal implementation detail.
- Strongly-typed, PureScript-friendly function that constructs the component. The body of such function usually consists of just a call to
createElement
(orcreateElement'
for childless components), its only purpose being the type signature. This function is what should be exported for use by consumers.
Classes and type aliases provided in this module, when applied to the constructor function, make it possible to pass only partial props to it, while still ensuring their correct types and presence of non-optional ones. This is facilitated by the undefined-is-not-a-problem library.
Example
The JSX file with component implementation
// `world` prop is required, `hello` and `highlight` are optional
export const MyComponent = ({ hello, world, highlight }) =>
<div>
<span>{hello || "Hello"}, </span>
<span style={ { color: highlight ? "red" : "" } }>{world}</span>
</div>
PureScript FFI module
module MyComponent(Props, myComponent) where
import Data.Undefined.NoProblem (Opt)
import Elmish.React (createElement)
import Elmish.React.Import (ImportedReactComponentConstructor, ImportedReactComponent)
type Props = ( world :: String, hello :: Opt String, highlight :: Opt Boolean )
myComponent :: ImportedReactComponentConstructor Props
myComponent = createElement myComponent_
foreign import myComponent_ :: ImportedReactComponent
PureScript use site
import MyComponent (myComponent)
import Elmish.React (fragment) as H
view :: ...
view = H.fragment
[ myComponent { world: "world" }
, myComponent { hello: "Goodbye", world: "cruel world!", highlight: true }
]