Binding To `withAuthenticator` in `aws-amplify-react` in ReasonML
Alain
Posted on August 19, 2019
Thanks to @bloodyOwl on Reason's Discord channel, @glennsl on stackoverflow and @hoichi in Reason.chat for help in finally figuring something out, even if I don't understand all the nuance yet.
The ReasonML community is the best.
https://reasonml.github.io/
The Binding
Let's say you are committed to doing everything in ReasonML
because every thing you learn can be applied somewhere else....like me. I have this working using Reason's javascript interop from a long long time ago but just had to get it working in Reason only so that I could know that I could do it. Here I am sharing the answer as a #notetoself and to save you any pain this might cause you.
Unbelievable, its this simple. The thing you and I will have to study is the various ways including modules with include App
and opening modules with open App
are different. Not doing that here because I don't know but I am showing you how to do it.
[@bs.module "aws-amplify-react"]
external withAuthenticator:
// takes a react component and returns a react component with the same signature
(React.component('props), bool) => React.component('props) =
"withAuthenticator";
module App = {
[@react.component]
let make = (~message) => <div> message->React.string </div>;
};
module WrappedApp = {
include App;
let make = withAuthenticator(make,true);
};
In index.re
use the binding as follows:
open BloodyOwlDemo;
ReactDOMRe.renderToElementWithId(<WrappedApp message="Thanks" />, "root");
Note
If you dont use include App
in WrappedApp
and instead call App.make
directly, like this:
module WrappedApp = {
// include App;
let make = withAuthenticator(App.make,true);
};
You will get this error:
>>>> Start compiling
[1/1] Building src/index-ReactHooksTemplate.cmj
We've found a bug for you!
/Users/prisc_000/working/DEMOS/bloody-authenticator/src/index.re 12:35-44
10 │
11 │ open BloodyOwlDemo;
12 │ ReactDOMRe.renderToElementWithId(<WrappedApp message="Thanks" />, "roo
t");
The value makeProps can't be found in WrappedApp
>>>> Finish compiling(exit: 1)
include App
copies over app to the WrappedApp
module instead of opening it which has some affect that I need to study.
After further discussion with @glennsl, he explains how you do the same thing without using include which copies over all the content of the App
.
He says, "it's basically the same, except instead of include App; you would define let makeProps manually, as if you were importing the component from js. Or if WrappedApp
should have the exact same props as App, you could also just alias makeProps
from App
: let makeProps = App.makeProps;
. That's exactly what include App
; does as well, except it also includes everything else in App
".
Below is what @glennsl is teaching us. This only uses makeProps
from our App
module.
module WrappedApp = {
let makeProps = App.makeProps;
let make = withAuthenticator(App.make,true);
};
Reproducing This App
This is App is the demo from the AwsAmplify docs found here: https://aws-amplify.github.io/docs/js/react.
Then add run yarn add bs-platform -D
and yarn add reason-react reason-scripts
. Also run touch index.re
and do your amplify configure
work here as you have it in the js
version. You can delete the js
version. There is a binding in this project here.
Then touch bsconfig.json
and add following to it.
{
"name": "react-hooks-template",
"reason": {
"react-jsx": 3
},
"sources": {
"dir" : "src",
"subdirs" : true
},
"package-specs": [{
"module": "commonjs",
"in-source": true
}],
"suffix": ".bs.js",
"namespace": true,
"bs-dependencies": [
"reason-react"
],
"gentypeconfig": {
"language": "untyped",
"module": "es6",
"importPath": "relative",
"reasonReactPath": "reason-react/src/ReasonReact.js",
"exportInterfaces": false,
"shims": {},
"debug": {
"all": false,
"basic": false
}
},
"refmt": 3
}
Show me the code.
Posted on August 19, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.