CSS Modules in ReasonMLEdit

Here's a super simple way to use CSS/SCSS modules with ReasonML.

Note: this guide assumes that you already have your environment set up for Reason and CSS/SCSS Modules and only covers how to import and use the CSS/SCSS modules in your re files.

I'm using ReasonReact in this example, but the principles/code snippets apply to any framework you want to use CSS/SCSS modules with.

Importing the styles

[@bs.deriving abstract] external styles: Js.Dict.t(string) = "./MyStyles.module.scss"

Replace the "./MyStyles.modules.scss" with the path to your CSS/SCSS module file.

Note: the file name does not have to include ".module" as demonstrated here. That's just the naming convention that I use.

You can rename styles to be anything else you prefer. This will be the variable name that you can use to access your styles in your Reason code.

Accessing the styles

Since we're importing the styles as a BuckleScript Js.Dict, you'll need to use their helper function to access the values.

Js.Dict.get(styles, "MyClassName")

This returns an option(string), which means that you need to handle the case where the className doesn't exist!

Here's a quick helper function for handling that:

/* Utils.re */

let getClassName = (dictionary: Js.Dict.t(string), className: string) => {
  switch (Js.Dict.get(dictionary, className)) {
  | Some(className) => className
  | None => ""
  };
};

This helper will return the className if it exists, or an empty string if not. So now instead of returning type option(string), you're returning string and can use this in your components!

After setting up this helper, you can use the styles in your ReasonReact components like this:

/* This is optional, but is handy so you don't have to
prefix the helper, i.e. Utils.getClassName */

open Utils;

let component = "App" |> ReasonReact.statelessComponent;

let make = _children => {
  ...component,
  render: _self => <div className={getClassName(styles, "MyClassName")} />
};

Full example

Here's everything out all together for easy copy/pasting:

/* Utils.re */

let getClassName = (dictionary: Js.Dict.t(string), className: string) => {
  switch (Js.Dict.get(dictionary, className)) {
  | Some(className) => className
  | None => ""
  };
};
/* MyComponent.re */

[@bs.deriving abstract] external styles: Js.Dict.t(string) = "./MyStyles.module.scss"

open Utils;

let component = "App" |> ReasonReact.statelessComponent;

let make = _children => {
  ...component,
  render: _self => <div className={getClassName(styles, "MyClassName")} />
};

Conclusion

Hope this saves you some time and gives you an extra push to use ReasonML in your new and existing projects - happy coding! SL