In JavaScript, React components can either be function or classes. This makes it easy to create functions that return components (factories if you will).
With ReasonReact though, if you want to use them with JSX, components need to be modules containing a make
function, which is a much more static construct.
Fortunately, Reason (through OCaml) has a great feature which is called functors. Think of it as a module function: it takes a module as parameter and returns a module.
The syntax
module Make = (Param: ParamType) => {
/* contents of the module to return */
};
Let's define a ParamType
first:
module type ParamType = {
type t;
let name: string;
let render: t => React.reactElement;
};
Now, let's create our functor. The following example is very short and now really useful, its goal is simply to show the syntax. Where functors shine is with more complicated components, where you just want to write a simple configuration to generate a component (e.g. big virtualised, paginated lists, sortables etc.)
module Make = (Param: ParamType) => {
type state = {
value: Param.t,
};
let component = React.reducerComponent("Demo" ++ Param.name);
let make = (~value: Param.t, _) => {
...component,
initialState: () => {value: value},
reducer: ((), _state) => React.NoUpdate,
render: ({state}) =>
<div style={ReactDOMRe.Style.make(~fontSize="32px", ())}>
/* some markup */
{Param.render(state.value)} </div>,
};
};
Now, in order to create a component, we just have to create a module with Make
:
module IntValue =
Make({
type t = int;
let name = "Int";
let render = x => x->string_of_int->React.string;
});
ReactDOMRe.renderToElementWithId(<IntValue value=2 />, "preview");