redraw/batteries/compose
Composing a basic feature in React and Redraw. All the time, Redraw
requires to compose components in order to get a better, wider interface.
To do this, Redraw provides a function redraw.compose, which extracts
the component from a ReactComponent, and provides it as a function for
the user to use. redraw/compose provides multiple helpers to simplify
the usage of ReactComponent and improve ergonomics over the default
redraw.compose.
Values
pub fn children(
component: redraw.ReactComponent(#(props, value)),
next: fn(fn(props, value) -> redraw.Element) -> redraw.ReactComponent(
a,
),
) -> redraw.ReactComponent(a)
Some components expects children, some components expects children as
render props, and some components only expects props. To manage children
or render props, with classic redraw.compose, it is expected to pass it
as a prop field, or as a tuple member.
fn my_component() {
use other <- redraw.compose(other_children())
use _ <- redraw.component_("MyComponent")
// Here we need to pass children in the props.
other(#(props, [
html.div([], []),
html.div([], []),
]))
}
It is such a common pattern, that compose.children helps to write such
components. When using compose.children, the ReactComponent props should
have kind #(props, children), but the resulting function will have kind
fn (props, children) -> Element (instead of
fn (#(props, children)) -> Element that would be provided by
redraw.compose). This improves ergonomics, for example by passing a list
as last element, or even to use with use in the case of a render prop.
// With children.
fn my_component() {
use other <- compose.children(other_children())
use _ <- redraw.component_("MyComponent")
// Here we can use `other` as any function expecting two arguments.
other(props, [
html.div([], []),
html.div([], []),
])
}
// With render.
fn my_component() {
use other <- compose.children(other_render())
use _ <- redraw.component_("MyComponent")
// Here we can use `other` as any function expecting a callback
// as last argument, `render` prop being a function.
use content <- other(props)
[
html.div([], []),
html.div([], []),
]
}
pub const compose: fn(
redraw.ReactComponent(b),
fn(fn(b) -> redraw.Element) -> redraw.ReactComponent(c),
) -> redraw.ReactComponent(c)
Allow to compose and use other components within a component. compose is
the only way to use components with other components. compose should be
called during the bootstrap phase of redraw, and let you access the
underlying component.
fn component() {
use other_component <- compose.compose(other_component())
h.div([], [
other_component(),
h.div([], []),
])
}
Re-export of the classic
redraw.composefor commodity and being able to useredraw/composefor all compositions.
pub fn static(
component: redraw.ReactComponent(Nil),
next: fn(fn() -> redraw.Element) -> redraw.ReactComponent(a),
) -> redraw.ReactComponent(a)
Static components are everywhere. Static components are defined as static
when they don’t refresh according to their props. They can refresh due to
some hooks, but otherwise they will never refresh at all. In Redraw, this is
illustrated when expected props are Nil. In that case, the component’s
props will never change, and they provide no value.
With classic redraw.compose, we are forced to explicitely provide Nil
to the component.
fn my_component() {
use other <- redraw.compose(other())
use _ <- redraw.component_("MyComponent")
// Here we have to explicitely pass `Nil`.
other(Nil)
}
compose.static provides better ergonomics, and avoid passing those Nil
props, and will inject Nil automtically. This simplifies usage, especially
when some other functions expects arguments looking like fn () -> a.
fn my_component() {
use other <- compose.static(other())
use _ <- redraw.component_("MyComponent")
// Here `Nil` is omitted.
other()
}