How to bind module as props

I have been use chakra-ui with example usage like this

<TagLeftIcon boxSize="12px" as={AddIcon} />

My question is How to make a binding for component <TagLeftIcon/> with props as with value is a Module ?

FYI, I have been read some article how to deal with module as props here (First-Class module), but I don’t know if the module is module bind.

Thank you

Hello.
Look at the example:

module TagLeftIcon = {
  @react.component
  let make = (~boxSize: string, @as("as") ~_as: int) => {
    <button> {React.string(`${boxSize}${_as->Belt.Int.toString}`)} </button>
  }
}

module App = {
  @react.component
  let make = () => {
    <TagLeftIcon boxSize="12px" _as={2} />
  }
}

Playground

If do you need to pass react component – it will harder.

Example:

type iconProps = {"type": string};

module TagLeftIcon = {
  @react.component
  let make = (~boxSize: string, @as("as") ~_as: iconProps => React.element) => {
    <button> {React.createElement(_as, {"type": "logo"}) } {React.string(boxSize)} </button>
  }
}

module SomeIcon = {
  @react.component
  let make = (~_type: string) => React.null
  
}
let renderIcon = (props: iconProps) => <SomeIcon _type={props["type"]} />

module App = {
  @react.component
  let make = () => {
    <TagLeftIcon boxSize="12px" _as={renderIcon} />
  }
}

More simple way:

type tagIcon

module TagLeftIcon = {
  type size = [#lg | #md | #sm]
  @react.component
  @module("@chakra-ui/react") external make: (~size: size=?, @as("as") ~_as: tagIcon =?) => React.element = "TagLeftIcon"
}

@module("@chakra-ui/icons") external addIcon: tagIcon = "AddIcon"

module App = {
  @react.component
  let make = () => <TagLeftIcon size={#lg} _as={addIcon} />
}

And one more way (more difficult for understanding, if you don’t use High Order Types)

module type Icon = {
  @react.component
  let make: (~_type: string) => React.element
}

module TagLeftIcon = {
  @react.component
  let make = (~boxSize: string, @as("as") ~_as: module(Icon)) => {
    let module(As) = _as
    <button> <As _type="logo" /> {React.string(boxSize)} </button>
  }
}

module SomeIcon: Icon = {
  @react.component
  let make = (~_type: string) => React.null
}

module App = {
  @react.component
  let make = () => {
    <TagLeftIcon boxSize="12px" _as={module(SomeIcon)} />
  }
}

Playground

And little interop for chakra-ui with your case:

module type Iconable = {
  @react.component
  let make: (~w: int=?, ~h: int=?) => React.element
}

module TagLeftIcon = {
  type size = [#lg | #md | #sm]
  @react.component
  @module("@chakra-ui/react") external make: (~size: size=?, @as("as") ~_as: module(Iconable)=?) => React.element = "TagLeftIcon"
}

module Icon: Iconable = {
  @react.component
  @module("@chakra-ui/icons") external make: (~w: int=?, ~h: int=?) => React.element = "AddIcon"
}

module App = {

  @react.component
  let make = () => <TagLeftIcon size={#lg} _as={module(Icon)} />
}

Playground

1 Like

Thanks for your answer.