Binding To `withAuthenticator` in `aws-amplify-react` in ReasonML
Tags: reason, bindings, awsamplify, bucklescript
Published: 2019-08-19 18:07:49

---
title: Binding To `withAuthenticator` in `aws-amplify-react` in ReasonML
published: true
description: How to use `withAuthenticator` in a ReasonML project
tags: ReasonML, Reason, bindings, aws-amplify, bucklescript
---

Thanks to @bloodyOwl on [Reason's Discord channel](https://discordapp.com/invite/reasonml), @glennsl on [stackoverflow](https://stackoverflow.com/questions/57548611/reasonml-binding-to-higher-order-functions/57561307#57561307) and @hoichi in [Reason.chat](https://reasonml.chat/t/resolving-error-this-call-is-missing-an-argument-of-type-authstate-option-authenticator-authdata-react-element/1620) for help in finally figuring something out, even if I don't understand all the nuance yet.

The [ReasonML](https://reasonml.github.io/) community is the best.
https://reasonml.github.io/
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/zr6yh8emobdcfdp0o9cc.png)

# 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.


```reason
[@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:

```reason
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:

```reason
module WrappedApp = {
  // include App;
  let make = withAuthenticator(App.make,true);
};
```

You will get this error:

```bsh
>>>> 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](https://reasonml.github.io/docs/en/module#extending-modules)

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.

```reason
module WrappedApp = {
  let makeProps = App.makeProps;
  let make = withAuthenticator(App.make,true);
};
```

[link](https://github.com/idkjs/bloody-authenticator/blob/9e9248a7693a7ae62c86ae6dd59565c314cdcc8e/src/GlennslDemo.re#L16-L19)

## 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](https://github.com/idkjs/bloody-authenticator/blob/master/src/aws/Amplify.re).

Then `touch bsconfig.json` and add following to it.

```json
{
  "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](https://github.com/idkjs/bloody-authenticator).