It's a minimal library, provides the one function to transform a JSX.t
tree into string
and a few helpers to make your life easier.
JSX.render
to render a JSX element into HTMLJSX.*
to construct DOM elements and DOM nodes (JSX.string
, JSX.int
, JSX.null
, JSX.list
, JSX.unsafe
)We stick to the HTML standard, so no react idioms like className
, no htmlFor
, etc.
let element = <span> {JSX.string("Hello world!")} </span>;
Note: reserved keywords aren't possible as props. For example: class
=> class_
or type
=> type_
.
let component = (~name, ()) => {
<div> <h1> {JSX.string("Hello, " ++ name ++ "!")} </h1> </div>;
};
JSX.render(<component name="lola" />);
> Note that the component
function needs to have a last argument of type unit
in order to work properly with labelled arguments. Explained on the OCaml manual: Functions with only labelled arguments, need a last non labelled argument to be able to be called as a non curried function.
This makes possible to compose any HTML and abstract those components away. ~children
is a prop that recieves the nested elements from the component invocation.
let hero = (~children, ()) => {
<main class_="fancy-hero"> {children} </main>;
};
JSX.render(<hero> {JSX.string("Hello, world!")} </hero>);
In this example, the hero
component is a function that takes a children
prop and returns a main
element with the class fancy-hero
. The children
prop is the nested elements from the component invocation.
make
functionmodule Button = {
let make = () => {
<button onclick="onClickHandler"> {JSX.string("Click me")} </button>;
};
};
JSX.render(<Button />);
// is equivalent to
JSX.render(<Button.make />);
let component = (~name, ~children, ()) => {
<div>
<h1> {("Hello, " ++ name ++ "!") |> JSX.string} </h1>
<h2> children </h2>
</div>;
};
JSX.render(
<component name="World"> {JSX.string("This is a children!")} </component>,
);
JSX.list
A component can receive more than one children, which is the case for the ul
element, but many other elements too. To make sure a list of elements is an element, use the JSX.list
function.
JSX.render(
<ul>
{["This", "is", "an", "unordered", "list"]
|> List.map(item => <li> {JSX.string(item)} </li>)
|> JSX.list}
</ul>,
);
There are other cases where you want to construct many JSX.element
without wrapping them in a HTML element, that's what Fragment
is for: <> ... </>
.
let component: JSX.element =
<>
<div class_="md:w-1/3" />
<div class_="md:w-2/3" />
</>;
let output = JSX.render(<component/>);
/* <div class="md:w-1/3"></div><div class="md:w-2/3"></div> */
HTML attributes are type-checked and only valid attributes are allowed. It also ensures that the value is correct.
<h1 noop=1> {JSX.string("Hello, world!")} </h1>
^^^
// Error: prop 'noop' is not valid on a 'h1' element.
<h1 class_=1> {JSX.string("Hello, world!")} </h1>
^
// Error: This expression has type int but an expression was expected of type string
And also in case of a misspell, it recommends the closest attribute
<div ?onClick />
^^^^
// Error: prop 'onClick' is not valid on a 'div' element.
// Hint: Maybe you mean 'onclick'?
let component = (~name, ()) => {
<div>
<h1> {JSX.string("Hello, " ++ name ++ "!")} </h1>
</div>;
};
JSX.render(<component name="World" />);
mlx is an OCaml syntax dialect which adds JSX syntax expressions
let component ~name () =
<div>
<h1> ("Hello, " ^ name ^ "!") </h1>
</div>
JSX.render <component name="World" />