How to use React Fragement?

reasonreact

#1

Hi all

How can I use https://reactjs.org/docs/fragments.html in ReasonReact?

Thanks


#2

You can create a small module for it, like

/* Fragment.re */
[@bs.module "react"] external fragment : ReasonReact.reactClass = "Fragment";

let make = children => ReasonReact.wrapJsForReason(~reactClass=fragment, ~props=Js.Obj.empty(), children);

and use it the same way as in vanilla react:

<Fragment>
  <ChildA/>
  <ChildB/>
  <ChildC/>
</Fragment>

#3

I defined Fragment as you told me above and I am using as following:

  <MainContainer>
      <Fragment>
        <p>{ReasonReact.string("Hello")}</p>
        <p>{ReasonReact.string("Hello")}</p>
      </Fragment>
  </MainContainer>

and still got the error message:

  We've found a bug for you!
  /home/developer/Desktop/reason-react/cockpit/src/App/AppContainer.re 20:7-25:22

  18 ┆   <div>
  19 ┆     <TopbarContainer />
  20 ┆     <MainContainer>
  21 ┆         <Fragment>
   . ┆ ...
  24 ┆         </Fragment>
  25 ┆     </MainContainer>
  26 ┆   </div>
  27 ┆ },

  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

ninja: build stopped: subcommand failed.
>>>> Finish compiling(exit: 1)
>>>> Start compiling
Rebuilding since [ [ 'change', 'AppContainer.re' ] ]
ninja: Entering directory `lib/bs'
[1/1] Building src/App/AppContainer-Cockpit.cmj
FAILED: src/App/AppContainer-Cockpit.cmj /home/developer/Desktop/reason-react/cockpit/src/App/AppContainer.bs.js src/App/AppContainer-Cockpit.cmi
/home/developer/Desktop/reason-react/cockpit/node_modules/bs-platform/lib/bsc.exe -bs-package-map cockpit  -bs-package-output es6:src/App -bs-assume-no-mli -bs-no-builtin-ppx-ml -bs-no-implicit-include -I /home/developer/Desktop/reason-react/cockpit/node_modules/reason-react/lib/ocaml -I /home/developer/Desktop/reason-react/cockpit/node_modules/bs-axios/lib/ocaml -I /home/developer/Desktop/reason-react/cockpit/node_modules/bs-webapi/lib/ocaml -I . -I src/Fragment -I src/Api -I src/Main -I src/Content -I src/Topbar -I src/App -I src/Sidebar  -w -30-40+6+7+27+32..39+44+45+101 -warn-error +5 -bs-suffix -nostdlib -I '/home/developer/Desktop/reason-react/cockpit/node_modules/bs-platform/lib/ocaml' -no-alias-deps -color always -bs-re-out -bs-super-errors -o src/App/AppContainer-Cockpit.cmj -c  src/App/AppContainer.mlast

  We've found a bug for you!
  /home/developer/Desktop/reason-react/cockpit/src/App/AppContainer.re 20:7-25:22

  18 ┆   <div>
  19 ┆     <TopbarContainer />
  20 ┆     <MainContainer>
  21 ┆         <Fragment>
   . ┆ ...
  24 ┆         </Fragment>
  25 ┆     </MainContainer>
  26 ┆   </div>
  27 ┆ },

  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

ninja: build stopped: subcommand failed.
>>>> Finish compiling(exit: 1)

What am I doing wrong?


#4

I also tried:

let make = (_children) => {
  ...component,
  initialState: () => {empty: 0},
  reducer: (_action: action, _state: state) => ReasonReact.NoUpdate,
  render: _self => {
    
    let mainChildren = [| <p>{ReasonReact.string("Hello")}</p>, <p>{ReasonReact.string("Hello")}</p> |];

    <Fragment>
      <TopbarContainer />
      <MainContainer>
          ...mainChildren
      </MainContainer>
    </Fragment>
  },
};

But still does not work.


#5

That’s odd.

Did you open ReasonReact or something? Or can you try it with just <div />s as children?

I am on Bucklescript 3.1.4 & Reason 3.2.0 but it did work on previous versions too.

EDIT: And I hope you use react@16.x.x as a dependency?


#6

(Just mentioning this here, because searching for how to use fragments lands here so other beginners might end up here and get the wrong idea.)

Fragments are now supported by default since version 0.5.0. No need to do custom wrappers as suggested above. Here is the official documentation page on reason-react and fragments

The syntax for using React fragments in reason-react is this:

<>
  <button label="foo"/>
  <button label="bar"/>
</>

The terse syntax may be easy to miss if you are looking hard for something like <Fragment> (this is what happened to me). I first found the answer in the release notes for version 0.5.0