0

I am trying to build my own <MySelect> component where the user passes in their own <option>s. Like this:

<MySelect label="Pick a color" onChange={...}>
    <option value="blue">(ReasonReact.string("Blue"))</option>
    <option value="red">(ReasonReact.string("Red"))</option>
    <option value="green">(ReasonReact.string("Green"))</option>
</MySelect>

But I don't understand how to handle the children within the MySelect. The docs (and here) doesn't show a full example.

Attempt

/* ... */
make = (~label, ~onChange, children) =>
    <label>
        <div>(ReasonReact.string(label))</div>
        <select onChange=onChange>
            ...children
        </select>
    </label>

I get

Error: function call with [@@bs.val "createElement"]  is a primitive with [@bs.splice], it expects its `bs.splice` argument to be a syntactic array in the call site and  all arguments to be supplied

Without the spread (so children instead of ...children) I get

Did you pass an array as a ReasonReact DOM (lower-case) component's children?
If not, disregard this. If so, please use `ReasonReact.createDomElement`:
https://reasonml.github.io/reason-react/docs/en/children.html

Here's the original error message
This has type:
  array('a)
But somewhere wanted:
  ReasonReact.reactElement

I am sure both these error messages combined with the docs tell me all that I need to know; there are just too many unknown words for me to make sense of it.

I have also attempted to google for examples (it would seem like a fairly normal usecase), but everywhere I find, they ignore the children entirely.

glennsl
  • 28,186
  • 12
  • 57
  • 75

1 Answers1

0

select is a DOM (lowercase) component so you'll need to use createDomElement. The relevant section in the docs is here: https://reasonml.github.io/reason-react/docs/en/children.html#pitfall. To modify your example a little bit with an example:

module MySelect = {
  let component = ReasonReact.statelessComponent("MySelect");

  let make = (~label, ~onChange, children) => {
    ...component,
    render: _ =>
      <label>
        <div> (ReasonReact.string(label)) </div>
        (
          ReasonReact.createDomElement(
            "select",
            ~props={"onChange": onChange},
            children,
          )
        )
      </label>,
  };
};

module Example = {
  let component = ReasonReact.statelessComponent("Example");

  let make = _children => {
    ...component,
    render: _ =>
      <MySelect label="test" onChange=(value => Js.log(value))>
        <option value="blue"> (ReasonReact.string("Blue")) </option>
        <option value="red"> (ReasonReact.string("Red")) </option>
        <option value="green"> (ReasonReact.string("Green")) </option>
      </MySelect>,
  };
};
glennsl
  • 28,186
  • 12
  • 57
  • 75
franky
  • 1,323
  • 1
  • 12
  • 13