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.