til/ReScript: FFI basics in React
When we write bindings we don't need to specify all the props that a third-party component can receive. By only binding to the props we use we will reduce the amount of noise and keep our API cleaner.
react-hot-toast is a small and simple package that displays beautiful notifications (toasts). Here are bindings to its
<Toaster> component and
We start by adding two decorators,
@react.component is the same as the one we use to annotate any React component.
@module("react-hot-toast") creates a binding that imports from an external package, in this case
We are happy with the defaults of the
<Toaster> so we define that the
make function takes a
unit, which in this case means no props, and returns a
React.element. Lastly, we set
"Toaster" as it is a named export.
The default export of
react-hot-toast is a function that takes a
string, but it also has variants for special cases such as success. Using the
@send decorator we can bind to this
success function. Calling this takes two steps as we first need to create the
Toaster.t parameter and then pass the text we want to display. The resulting code is in the
Most of the times we want to be able to pass some props to the React components we bind to, so here's another example that binds to
The difference compared to the binding without props is that the
make function accepts:
children: string- The children of the component, i.e. the content, is a
stringwhich will be parsed as markdown to HTML
className: string=?- The
?denotes that the
classNameis an optional property
Also, note that we are using
"default" which imports the default export of the package.
Binding to a React hook is like binding to any other function. Here's an example of a binding to
It's not necessary to create a module for the binding, but I think it encapsulates the binding nicer. The hook takes a
bool for the initial state and returns
Render props aren't very common anymore following the introduction of React hooks, but we still encounter them sometimes. Here's an example of binding to
Now it's getting more complex and it's the first time we are using a type parameter aka generic! We start by defining a React component for
<Formik>. It accepts two props:
children: renderProps<'values> => React.element- The child should be a function that gets the
renderPropsrecord (with the generic
'values) and returns a
initialValues: 'values- A record with the initial data of the form
We define the type of the values in
type form and pass a record of that type to Formik's
initialValues prop. After this, the type of
values in the render prop will automatically be of the type
form since it uses the same type parameter as
initialValues in our binding.
Note: Formik has multiple APIs for creating forms and this is not a fully functioning binding. It's just to demonstrate the use of render props.
Sometimes we need to reach out and connect to a global variable. This is exactly what we did in the previous post about connecting to localStorage. I'll include the code example here but if you want to learn more about it see the previous post.
@val @scope("localStorage") external getItem: string => Js.Nullable.t<string> = "getItem" @val @scope("localStorage") external setItem: (string, string) => unit = "setItem"
- Cory House. (2022-02-19). Tweet
- ReScript: Creating a React component
- ReScript: Using React components
- ReScript: Adding a third-party library
- ReScript: Using useState in rescript-react
- ReScript: Using useReducer in rescript-react
- ReScript: Adding new actions to an existing useReducer
- ReScript: Using useContext in rescript-react
- ReScript: Connect to localStorage using FFI and functors
- ReScript: FFI basics in React
- how I add Tailwind to my ReScript projects