How to write rescript bindings for a react library
Tags: rescript, react, functional
Published: 2021-08-23 01:28:36

---
title: How to write rescript bindings for a react library
published: true
description: 
tags: rescript, react, fp
//cover_image: https://direct_url_to_image.jpg
canonical_url: https://arbaaz.io/posts/how-to-write-rescript-bindings-for-a-react-library
---


Bindings are nothing but  [FFI](https://en.wikipedia.org/wiki/Foreign_function_interface) 

According to wiki:
> A foreign function interface (FFI) is a mechanism by which a program written in one programming language can call routines or make use of services written in another.

ReScript bindings are just an unsafe direct-access mechanism to the JS world. Just some external declarations and some type definitions.

In this post, we are going to write few bindings for the antd library.

Let's get started with a very simple component that doesn't accept any props or children.

### Named Import 

#### Component
```res
// closeCircleOutlined.jsx
import { CloseOutlined } from '@ant-design/icons'
/* npm install --save @ant-design/icons */

ReactDOM.render(
 <CloseOutlined />,
 mountNode,
);
```
#### Binding: 
```
// Bindings.res
module CloseCircleOutlined = {
 @module("@ant-design/icons") @react.component
 external make: React.element = "CloseCircleOutlined"
}

```


### Default Import
```
// Bindings.res

// import CloseOutlined from '@ant-design/icons'
module CloseOutlined = {
 @module("@ant-design/icons") @react.component
 external make: React.element = "default"
}

```

I'm assuming you know what decorators are. If you haven't read about them before then you can read [here](https://rescript-lang.org/docs/manual/latest/attribute)

The ** basic structure ** is 
```
module ComponentName = {
 @module("<node_module_name>") @react.component
 external make: React.element = "<NamedImport> or <default>"
}

```


This component doesn't accept any props yet.  

Let's write another binding for a [button](https://ant.design/components/button/). 

#### Component:
```
import { Button } from 'antd';

ReactDOM.render(
  <>
    <Button shape="circle">Circle Button</Button>
    <Button shape="round">Round Button</Button>
  </>,
  mountNode,
);
```
#### Binding:
Copy the structure and fill in the names.
```
// Bindings.res
module Button = {
 @module("antd") @react.component
 external make: React.element = "Button"
}

```


At this point, you can only use the button as 
```
<Button/>
```
not as
```   
<Button shape="circle">Text</Button>
```
### Props

Let's add a `shape` prop.
```
// Bindings.res
module Button = {
 @module("antd") @react.component
 external make: (~shape:string) => React.element = "Button"
}
```
Remember, we have to declare each **prop** as a  **Named argument.**

### Keyword prop
Now, here is a little tricky one. Let's add a `type` prop. 
```
// Bindings.res
module Button = {
 @module("antd") @react.component
 external make: (~\"type": string, ~shape:string) => React.element = "Button"
}
```
`type` is a keyword in a rescript so whenever we use a  **keyword** we have to escape it.

### Children
To accept the **child component**, we will use `children` named argument 
```
// Bindings.res
module Button = {
 @module("antd") @react.component
 external make: (~children:React.element, ~shape:string, ~\"type": string) => React.element = "Button"
}
```
```
// App.res
ReactDOM.render(
 <Button \"type"="primary" shape="circle">{React.string("Click me")}</Button>, 
 mountNode
)
```




### React prop
```
// Bindings.res
module Button = {
 @module("antd") @react.component
 external make: (~icon: React.element, ~children:React.element, ~shape:string, ~\"type": string) => React.element = "Button"
}
```

```
// App.res
ReactDOM.render(
 <Button icon={<DownloadOutlined />} shape="circle" \"type"="primary">{React.string("Click me")}</Button>, 
 mountNode
)
```

That's all folks!