What is bucklescript looking for satisfy the Functions are not valid as a React child.
error being produced by the following example.
I have this binding to withAuthenticator
from aws-amplify-react
.
[@bs.deriving abstract]
type props = {
[@bs.as "Comp"]
comp: React.element,
[@bs.optional] includeGreetings: bool,
};
[@genType.import ("aws-amplify-react", "withAuthenticator")] [@react.component]
external make:(
~props:props,
) => React.element = "withAuthenticator";
let default = make;
In Demo.re
I use the binding as follows:
let props = {
WithAuthenticator.props(
~comp={
<App />;
},
~includeGreetings=true,
(),
);
};
Js.log(props);
[@react.component]
let app = () => <WithAuthenticator props />;
Then in App.js
I use Demo.re
like so:
import Amplify from 'aws-amplify';
import {app as App } from './Demo.bs';
import awsconfig from './aws-exports';
import './App.css';
Amplify.configure(awsconfig);
export default App;
Which produces the following error:
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.
in withAuthenticator (created by Demo$app)
in Demo$app (at src/index.js:7)
I would like to understand what this means in order to deal with when it comes up again.
This is what the compiled bucklescript code is in Demo.bs.js
:
// Generated by BUCKLESCRIPT, PLEASE EDIT WITH CARE
'use strict';
var React = require("react");
var App$ReactHooksTemplate = require("./App.bs.js");
var WithAuthenticator$ReactHooksTemplate = require("../aws/WithAuthenticator.bs.js");
var props = {
Comp: React.createElement(App$ReactHooksTemplate.make, { }),
includeGreetings: true
};
console.log(props);
function Demo$app(Props) {
return React.createElement(WithAuthenticator$ReactHooksTemplate.make, {
props: props
});
}
var app = Demo$app;
exports.props = props;
exports.app = app;
/* props Not a pure module */
Reproduction of this issue can be found here.
Update:
Here I am trying to follow up on @glennsl's comments/answer below.
// define a type modeling what `withAuthenticator` is expecting
[@bs.deriving abstract]
type props = {
[@bs.as "Comp"]
comp: React.element,
[@bs.optional]
includeGreetings: bool,
};
// use bs.module instead of gentype
[@bs.module ("aws-amplify-react", "withAuthenticator")]
external withAuthenticator: props => React.component(props) =
"withAuthenticator";
module AppWithAuthenticator = {
[@bs.obj]
external makeProps:
(~children: 'children, unit) => {. "children": 'children} =
"";
let make = props => withAuthenticator(props);
};
This is how it might be used, but doesnt compile.
module AppWithAuth = {
let props = {
props(
~comp={
<App />;
},
~includeGreetings=true,
(),
);
};
[@react.component]
let make = () => {
<AppWithAuthenticator props />;
};
};
compile error:
>>>> Start compiling
[1/3] Building src/aws/AuthenticatorBS-ReactHooksTemplate.cmj
We've found a bug for you!
/Users/prisc_000/working/DEMOS/my-app/src/aws/AuthenticatorBS.re 34:6-25
32 │ [@react.component]
33 │ let make = () => {
34 │ <AppWithAuthenticator props />;
35 │ };
36 │ };
This call is missing an argument of type props
Something along these lines should work:
[@genType.import ("aws-amplify-react", "withAuthenticator")]
external withAuthenticator : (React.component('a), bool) => React.component('a) = "withAuthenticator";
module AppWithAuthenticator = {
[@bs.obj]
external makeProps: (~children: 'children=?, unit) => {. "children": 'children } = "";
let make = withAuthenticator(App.make, true);
};
ReactDOMRe.renderToElementWithId(<AppWithAuthenticator />, "root");
external withAuthenticator : ...
declares the external HOC constructor as a function that takes a react component and a bool, and returns a component that will accept the exact same props due to the 'a
type variable being used in both positions.
module AppWithAuthenticator ...
applies the HOC constructor to the App
component and sets it up so that it can be used with JSX. This is basically the same as importing a react component directly, except we get the external component by way of a function call instead of importing it directly.
Finally, the last line just demonstrates how it could be used.
Note that I obviously haven't tested this properly as I don't have a project set up with aws-amplify
and such. I've also never used genType
, but it seems pretty straightforward for this use case.