DEV Community

Alain
Alain

Posted on

Binding To `withAuthenticator` in `aws-amplify-react` in ReasonML

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/
Alt Text

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.

include in docs

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);
};

link

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.

Top comments (0)