Is there any way to make this switch statement more vertical and with less React.null's?

I’m using the rescript-relay code generator that gives me many optional types.

      {switch menu {
      | Some({menuItems: None}) => React.null
      | Some({menuItems: Some({nodes})}) =>
        switch nodes {
        | Some(nodes) =>
          nodes
          ->Array.map(node =>
            switch node {
            | Some(n) =>
              <div>
                <p> {"Yo"->React.string} </p>
                <p> {n.label->Option.getWithDefault("")->React.string} </p>
              </div>
            | None => React.null
            }
          )
          ->React.array
        | None => React.null
        }
      | None => React.null
      }}

I came up with this approach, but IDK if that’s idiomatic in RES

      {menu.menuItems->Option.mapWithDefault(React.null, ({nodes}) =>
        nodes
        ->Array.map(node =>
          node->Option.mapWithDefault(React.null, n =>
            <div key={n.label->Option.getWithDefault("")}>
              <p> {"Yo"->React.string} </p>
              <p> {n.label->Option.getWithDefault("")->React.string} </p>
            </div>
          )
        )
        ->React.array
      )}```

It’s fine.
I don’t think you can get rid of more React.nulls

Your original example can also be optimized to this:

  switch menu {
  | Some({menuItems: Some({nodes: Some(nodes)})}) =>
    nodes
    ->Array.map(node =>
      switch node {
      | Some(n) =>
        <div>
          <p> {"Yo"->React.string} </p>
          <p> {n.label->Option.getWithDefault("")->React.string} </p>
        </div>
      | None => React.null
      }
    )
    ->React.array

  | _ => React.null
  }
3 Likes

You could use Array.keepMap instead of mapping to React.null

3 Likes

You’re right. e.g.:

switch menu {
| Some({menuItems: Some({nodes: Some(nodes)})}) =>
  nodes
  ->Array.keepMap(node =>
    node->Option.map(n =>
      <div key={n.label->Option.getWithDefault("")}>
        <p> {"Yo"->React.string} </p>
        <p> {n.label->Option.getWithDefault("")->React.string} </p>
      </div>
    )
  )
  ->React.array

| _ => React.null
}
1 Like

this is already answered but now I have another question the list is option<array<option<…>>> is there any fn that can easily traverse?