ReScript is a new compile-to-Javascript language that uses OCaml as an intermediate language, thus enforcing a degree of type safety that Typescript can only dream about. It was written by the some of the same people who wrote React, and it has very good React support.

Storybook is a popular tool for documenting custom-made React Components. It allows you to show those components in their natural state, with as little styling as necessary to support the use case.

MDX is a format that allows you to mix Markdown and JSX. Storybook provides an MDX interface for writing rich documentation.

This is a very short explanation illustrating how to use Storybook MDX with ReScript. For those of you unfamiliar with ReScript, they are a new Javascript syntax that parses directly to OCaml and then into native and fairly performant Javascript.

Background

There were three generations of ReScript:

  • Bucklescript, a project by Bloomberg News that converted OCaml directly into Javascript. The Bucklescript compiler is at the root of all of future projects.
  • ReasonML, a compiler that converted a Javascript-like syntax into the OCaml language, and then called Bucklescript. ReasonML was supposed to be "Javascript friendly," and looked much more like the Algol-like syntax of Javascript and less the indented style of OCaml.
  • ReScript, the latest iteration of the ReasonML compiler with a cleaner and much better Javascript interop.

I enjoy working in ReScript, but at this point I can't find a good use for it in my own ecosystem. There are pain points with Javascript interop that I still find unacceptable. There's ReasonReact, but trying to integrate a lot of third-party React components can get dreary very quickly.

I wish that weren't the case, but until ReScript matures a little more I'm not going to be using it professionally. But I did figure out how to create a React component using ReScript, and then show it using Storybook's MDX feature, which is, frankly, the cool part.

The steps are straightforward. First, assuming you already have a ReScript project, add Storybook:

$ yarn global add storybook
$ npx sb init

Storybook installs MDX by default, so you should have it.

☝ By default, every ReasonReact functional component exports itself as a ReScript module, a container similar to a library but with much more capability, and that module exports a function named make as the functional React component name.

☝ By default and convention, the Bucklescript compiler converts all ReScript files, ending in .res, into Javascript with a .bs.js extension.

☝ MDX files have two parts: The header, and the body. The header is everything before the first blank line, and is interpreted as Javascript directives. After a blank line, everything is treated as Markdown unless it is obviously parsable as JSX, in which case it is treated as JSX.

☝ ReScripts's internal types come with internal type annotations that continue to live in other code. If you want to use a React object that takes a ReScript linked list, you will want to generate that object with ReScript.

With this knowledge, a complete example of importing a ReScript object into an MDX documentation module is simple:

import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
import { make as Card } from "../Card.bs";

<Meta title="MDX/Card" component={Card} />

A simple Card API:

<Card content={"This is a test"}/>

And that's it. Include the component with { make as Component } and include the .bs part of the extension (but not the .js that will be visible in the filesystem).

If you want to use a more complex dataset as your example argument to a Storybook React component, especially one written using ReasonReact, you're going to have to encapsulate that dataset in ReScript. Look in ./src/stories/NoncardSupport and the accompanying compiled output to see how you use Storybook to demo a ReasonReact component that takes a Bucklescript linked list.

Credits

The example code is derived from Juan Pedro Villa Isaza's fantastic tutorial, Nonsense! Getting started with Reason and ReasonReact , although I have separated the effectful and rendering components into separate modules, the better to illustrate how to test the visual components of the renderer.

Source Code

A working example is available on Github

License

The example code was initialized with yarn, bsb -init, and npx sb init. Mr. Isaza's work is clearly his. The conversion from ReasonML to Rescript, the refactor into effect and view, and the storybook additions are entirely my own.

My contributions are Copyright Elf M. Sternberg (c) 2019, and licensed with the Mozilla Public License vers. 2.0. A copy of the license file is included in the root folder of the repository.