Low level APIs to create components

The following APIs are used by JSX itself to create elements.

React.createElement: (React.component<'props>, 'props) => React.elements

React.createElementVariadic: 
(React.component<'props>, 'props, array<React.element>) => React.element

React.cloneElement: (React.element, 'props) => React.element

React.createElement

module Movie = {
  @react.component
  let make = (~title: string, ~desc: string) => {
    <div>
      <h1> {title->React.string} </h1>
      <p> {desc->React.string} </p>
    </div>
  }
}

@react.component
let make = () => {
  <div>
    {React.createElement(Movie.make, {"title": "Lopper", "desc": "One of the best sifi movies."})}
  </div>
}

React.createElementVariadic

module Stack = {
    @react.component
    let make = (~width: option<string>=?, ~height: option<string>=?, ~children: option<React.element>=?) => {
        let ms = ReactDOM.Style.make
        let style = switch (width, height) {
            |(Some(w), Some(h)) => ms(~width=w, ~height=h, ())
            |(Some(w), None) => ms(~width=w, ~height="auto", ())
            |(None, Some(h)) => ms(~width="auto",~height=h, ())
            |(None, None) => ms(~width="auto", ~height="auto", ())
        }
       <div className="flex flex-col flex-wrap" style>
       { switch children { |Some(c) => c |None => React.null } }
       </div> 
    }
}

module Movie = {
  @react.component
  let make = (~title: string, ~desc: string) => {
    <div>
      <h1> {title->React.string} </h1>
      <p> {desc->React.string} </p>
    </div>
  }
}

@react.component
let make = () => {
  <div>
    {React.createElementVariadic(Stack.make, {"width": Some("100%"), "height": Some("50%") , "children": None}, [
        <div>{"My List"->React.string}</div>,
        <Stack width="50%" height="50%">
            <div>{"Scifi Movies"->React.string}</div> 
            <Movie title="Dark" desc="The best scifi series I've ever watched"/>
        </Stack> 
    ])}
  </div>
}

React.cloneElement

Useful to add additional attributes to the original element - like data- attributes

let hello = <div className="text-slate-900"> {"Hello"->React.string} </div>
@react.component
let make = () => {
  <div>
    {React.cloneElement(hello, 
     {"className": "text-red-900 text-xl", "data-theme": "red"})}
  </div>
}

generated <div class="text-red-900 text-xl" data-theme="red">Hello</div>