Trouble Importing From JS

reasonreact

#1

Hi,

I am trying to convert a ReasonReact.wrapJsForReason to JSX:3.

This was the old:
[@bs.module "./GraphDownloadButtons"] external graphDownloadButtons: ReasonReact.reactClass = "default";

let make = (~graphType=?, ~graph: graphRef, ~filenames, ~downloadOptions, children) =>
  ReasonReact.wrapJsForReason(
    ~reactClass=graphDownloadButtons,
    ~props={
      "graphType": Js.Nullable.fromOption(graphType),
      "graph":
        switch (graph) {
        | ReactRef(v) => Obj.magic(v)
        | DomRef(v) => Obj.magic(v)
        },
      "filenames": Js.Dict.fromList(filenames),
      "downloadOptions": Js.Dict.fromList(downloadOptions),
    },
    children,
  );

And here is the new:
[@bs.module “./GraphDownloadButtons”][@react.component]
external make: (~graphType=?, ~graph: graphRef, ~filenames, ~downloadOptions, children) => React.element = “default”;

React.element is throwing me an Error: Syntax error but unsure why.

I have successfully updated other ReasonReact.wrapJsForReason, but this one is giving the syntax error.

Thanks in advance for any insights.

Also as an aside, how come there is no ReasonReact topic to select, or should I be posting these types of questions elsewhere?


#2

When making a binding like this, all of the props need to be typed explicitly. In addition, in JSX3 children is a labelled argument like all others.

Try this (replacing string with your own types):

[@bs.module "./GraphDownloadButtons"] [@react.component]
external make: (~graphType: string=?, ~graph: graphRef, ~filenames: array(string), ~downloadOptions: string, ~children: React.element) => React.element = "default";

If you need to do some transformation on the props (like Js.Dict.fromList) you’ll likely need to drop [@react.component] macro and write the binding by hand. See Complex bindings with the new [@react.component]? for an example.


#3

Amazing, thanks! And you even guessed the right type :slight_smile:


#4

Actually just one more question if you don’t mind.

I am still getting the error

Error: This expression has type
         (~graphType: 'a=?, ~graph: GraphDownloadButtons.graphRef,
         ~filenames: list((Js.Dict.key, 'b)),
         ~downloadOptions: list((Js.Dict.key, 'c)), 'd) =>
         ReasonReact.component(ReasonReact.stateless,
                                ReasonReact.noRetainedProps,
                                ReasonReact.actionless)
       but an expression was expected of type
         React.component('e) = 'e => React.element

I thought the external make would give a React.component('e) = 'e => React.element


#5

Can you post the code that triggers the error? Ideally also the external binding. Also just to verify: the project must be configured with JSX version 3 in bsconfig.json:

  ...
  "reason": {
    "react-jsx": 3
  },
  ...

#6

Hey @yawaramin, thanks for the quick response and sorry for my delayed. (In the interim I had just downgraded a new components to jsx2 instead of trying to upgrade the rest).

Just trying to nest the component into a jsx: 3 component triggers this:

    <GraphDownloadButtons
     graphType="Bar Chart"
     graph={GraphDownloadButtons.DomRef(barChartGraph(i))}
     filenames=[("default", filename(~cellSubset, ~selectedFeature))]
     downloadOptions=GraphDownloadButtons.DownloadOptions.defaults
   />

We are floating between jsx 2 and 3 so any component with version 3 has [@bs.config {jsx: 3}]; at the top of the file.

So both the file I am trying to nest the component inside, and the nested component are [@bs.config {jsx: 3}]; and it gives me this error.