Is this the correct use for keepmap?

I’m confused since node => node seems awkward to me.

  <ul className="flex gap-2 text-xl">
    {menu.menuItems.nodes
    ->Array.keepMap(node => node)
    ->Array.map(node => <li key=node.path> {React.string(node.label)} </li>)
    ->React.array}
  </ul>

I have written the same thing a few times. Maybe a separate function (keepSomes?) would be clearer.

1 Like

would love to use identity fn but I’m not sure if it exists in rescript

I think if you write this as its own function (We have Array.catOptions), you can write an external identity function that saves you creating a temp function repeatedly. fwiw.

external identity: 'a => 'a = "%identity"

let catOptions = (arr: array<option<'a>>): array<'a> => {
  arr->Belt.Array.keepMap(identity)
}
1 Like

Using a map after keepMap is partially redundant since you can combine them like this:

  <ul className="flex gap-2 text-xl">
    {menu.menuItems.nodes
    ->Array.keepMap(x =>
      switch x {
      | Some(node) => Some(<li key=node.path> {React.string(node.label)} </li>)
      | None => None
      }
    )
    ->React.array}
  </ul>

It’s more verbose than your original version, but it’s more efficient since you don’t have to map over the array twice.

You can make it more concise with the option helper functions:

  <ul className="flex gap-2 text-xl">
    {menu.menuItems.nodes
    ->Array.keepMap(
      Option.map(_, x => <li key=x.path> {React.string(x.label)} </li>),
    )
    ->React.array}
  </ul>

1 Like

We have a helper for this at Carla

// OptionExtra.res
let values = Belt.Array.keepMapU(_, (. a) => a)

And to ensure that it’s used instead of keepMap I’ve added a eslint rule:

"no-restricted-syntax": [
   "error",
   {
     "selector": "CallExpression[callee.object.name='Belt_Array'][callee.property.name='keepMap'] > FunctionExpression[body.body.0.type='ReturnStatement'][body.body.0.argument.type='Identifier']",
     "message": "Use OptionExtra.values instead."
   },
]
1 Like