Cannot read property 'node' of undefined

interop

#1

I’m trying to write a React component in Reason and wrap it for JS. Here’s my code:

open ReasonReact;

let component = statelessComponent("Topbar");

let make = _children => {
  ...component,
  render: _self => <div> (stringToElement("hello")) </div>
};

let default = wrapReasonForJs(~component, _jsProps => make([||]));

But when importing this module from JS, I get the following compilation error:

./src/components/topbar/index.bs.js
Module build failed: TypeError: Cannot read property 'node' of undefined

What did I miss?


#2

Can you show the import code on the JavaScript side?


#3

Sure:

import TopBar from '../../components/topbar/index.bs'


#4

What happens if you try:

import {default as TopBar} from '../../components/topbar/index.bs'

?

I would have expected BS to export default in the generated JS like: export $$default, but it seems to be exporting it like export {$$default as default}.

Now as far as I know, that won’t actually succeed in exporting the variable as the default export. So this might be a BuckleScript bug. Try it out and if my suggestion works, can I ask that you file a bug against https://github.com/BuckleScript/bucklescript ?


#5

default is a special named export so what Bucklescript is doing is fine.


#6

@yawaramin still getting the same error unfortunately.

If it helps, here’s the compiled JS output:

// Generated by BUCKLESCRIPT VERSION 2.2.2, PLEASE EDIT WITH CARE

import * as React from "react";
import * as ReasonReact from "reason-react/src/ReasonReact.js";

var component = ReasonReact.statelessComponent("Topbar");

function make() {
  var newrecord = component.slice();
  newrecord[/* render */9] = (function () {
      return React.createElement("div", undefined, "hello");
    });
  return newrecord;
}

var $$default = ReasonReact.wrapReasonForJs(component, (function () {
        return make(/* array */[]);
      }));

export {
  component ,
  make ,
  $$default ,
  $$default as default,
  
}
/* component Not a pure module */

#7

It’s a pretty standard Bucklescript output. I can’t see anything wrong with it. If you could make a reproducible test case, it would be helpful. I suspect this is something with your environment setup.


#8

I just found out that if I manually replace React.createElement("div", undefined, "hello") with React.createElement("div", {}, "hello") then it compiles. Or I could add any prop to <div> in index.re and it will work.

So seems like the problem is that ReasonReact is passing undefined to React.createElement when there’s no prop. Can that be considered a bug?


#9

Yep. This is a bug. Cc @chenglou


#10

Passing undefined to createElement is idiomatic (first example on the reactjs.org page actually). Could you show a small repro repo?


#11

Hmm. I never see undefined in real world (probably everyone uses JSX), babel outputs null and this page uses null too https://reactjs.org/docs/react-without-jsx.html


#12

@chenglou did you link to the wrong page? Your link sent me to React’s home page.

My impression is also that people usually pass null to createElement.

Here you can see the source code for createElement. It does seem to be only checking for null.


#13

The first example on the homepage in non-jsx view accepts null. undefined also works, as shown in the check here: https://github.com/facebook/react/blob/2cf9063318014dcc9a4839bb15ebb89a55198fce/packages/react/src/ReactElement.js#L181

If you have a github repo, we can try debugging it.


#14

Mystery solved. This issue disappeared after I upgraded react-scripts from 1.0.14 to 1.1.1. Not sure why though.


#15

Heavily recommend our bsb -init workflow instead btw: https://reasonml.github.io/reason-react/docs/en/installation.html#bsb


#16

out of curiosity, what is the JS output now after the upgrade?