Working with Optional Data
If you're coming from JavaScript, optional data can be a real pain. ReasonML removes a whole class of null and undefined bugs which makes your code safer and easier to write, but it takes some good examples to get you there :smile:
ReasonML uses the option type to represent optional data. As defined in the standard library here.
Here are a few examples of how to work with optional data in ReasonML, using the Belt library from melange.belt.
Accessing Optional Nested Data
Say you have have an array of colors and you want to match one of those colors:
let selected = colors->Belt.Array.getBy(c => c##id === id);
// Javascript
const selected = colors.find(c => c.id === id);
In both cases selected could be optional. The compiler may yell at you to handle that case, here's how you could handle it:
let label = selected->Belt.Option.mapWithDefault(
"Select a Color",
selected => selected##name
);
What this is doing: "if selected exists, go look into selected##name otherwise return Select a Color".
Read more about mapWithDefault here.
Something or Nothing
We need to grab the name of the person, but we also know that name can come back as undefined. We still want that label to be a string.
/* create the type for the record, totally ok that it's the same name! */
type person = {
name: option(string)
};
let person = {
name: None
};
let label = switch(person.name) {
| Some(name) => name
| None => "Peter"
}
You can also use Belt.Optional.getWithDefault which is sugar for above:
let label = Belt.Option.getWithDefault(person.name, "Peter");
If you need to return null instead of a component:
<div>
{
switch (person.name) {
| Some(name) => <Name name="Peter" />
| None => React.null
}
}
</div>;
Read more about getWithDefault here.