Quickwin good practices for ReasonReact



I want to keep this thread active with small hints and tips for ReasonReact good practices.
Feel free to contribute with more snippets!

Dealing with options within JSX


	->Belt.Option.map(user => <p>{React.string(user##name)}</p>)


  ->Belt.Option.getWithDefault({ "name": "" })
  ->(user => {

I have seen some beginners prefer the latter when starting to code in Reason probably because they are used to obj || {name: ''} in JS but the first scales much better so you don’t have to change a default value if the shape of your data changes


You can also use Belt.Option.mapWithDefault to combine the two steps into one:

  data##user->Belt.Option.mapWithDefault(React.null, user =>


Using React.null is so common that I have created a module Render with a map function, like this:

 If [optionValue] is [Some(value)], returns [f(value)]; otherwise returns [React.null]
let map: (option('a), 'a => React.element) => React.element =
  (opt, f) =>
    switch (opt) {
    | None => React.null
    | Some(item) => f(item)

and then:

{data##user->Render.map(user => <p>{React.string(user##name)}</p>)}

and so on for get, List.getByIndex, …


Another option/nullable situation: refs.

Here’s the helper:

let currentHtmlIter = (ref, ~f) => {
  ->Js.Nullable.iter((. el) => el->Webapi.Dom.Element.unsafeAsHtmlElement->f);

Here’s a usage example:

  let presentParagraphRef = React.useRef(Js.Nullable.null);

  let presentParagraphIter = Ref.currentHtmlIter(presentParagraphRef);

    () => {

Whether or not ~f should be a labeled argument is debatable, of course. I prefer labeled because then the helper can be used both with fast pipes and also in its curried form, like above. What can I say, I like Jane Street Base’s approach where all but one argument are labeled :man_shrugging: