To learn reason and reason-react, I'm working on a simple “Things 2 Do” app (see source code on GitHub).
I have a TodoItem component that should be rendered with strike-through style when the item has been completed.
I try to solve this by creating a record with various styles, similar to CSS classes, one root style and one for completed items.
type style = {
root: ReactDOMRe.style,
completed: ReactDOMRe.style
};
let styles = {
root: ReactDOMRe.Style.make(), /* add root styles here */
completed: ReactDOMRe.Style.make(~opacity="0.666", ~textDecoration="line-through", ())
};
If the prop completed is true, I combine the root style with the completed style, otherwise I just use the root, like this:
let style = styles.root;
let style = item.completed ? ReactDOMRe.Style.combine(style, styles.completed) : style;
This works, but it seems clunky, so I'm wondering: Is there a more elegant solution, e.g. using a variant and a switch statement?
What is the idiomatic way to create styles for a Reason-React component that depend on props?
Here is the full code of my component:
type item = {
id: int,
title: string,
completed: bool
};
type style = {
root: ReactDOMRe.style,
completed: ReactDOMRe.style
};
let str = ReasonReact.stringToElement;
let component = ReasonReact.statelessComponent("TodoItem");
let styles = {
root: ReactDOMRe.Style.make(), /* add root styles here */
completed: ReactDOMRe.Style.make(~opacity="0.666", ~textDecoration="line-through", ())
};
let make = (~item: item, ~onToggle, _) => {
...component,
render: (_) => {
let style = styles.root;
let style = item.completed ? ReactDOMRe.Style.combine(style, styles.completed) : style;
<div style>
<input
_type="checkbox"
onChange=((_) => onToggle())
checked=(Js.Boolean.to_js_boolean(item.completed))
/>
<label> (str(item.title)) </label>
</div>
}
};
I don't think there's anything that can be called idiomatic yet. The area is quickly changing, and even I have some ideas of my own on how to improve it, but this is more or less how I do it now using bs-css:
module Styles = {
open Css;
let root = completed => style([
color(white),
opacity(completed ? 0.666 : 1.),
textDecoration(completed ? LineThrough : None)
]);
}
...
render: _self =>
<div className=Styles.root(item.completed)>
...
</div>