Skip to main content

Web Components

Duck has support for both Server Side Rendering using duckx and Client Components with jsx and preact

React components

Components can take an optional props parameter that represents the server side rendered properties They also have an implicit props parameter for everyting passed on the client from other components

src/strings.duck
component NoSSRProps() jsx {
return <div>i don't take any ssr props, but i can take client props {props.some_client_value}</div>;
}

component NoPropsAtAll() jsx {
return <div>i don't take props at all</div>;
}

component Counter(props: { initial_value: Int }) jsx {
// Write this component using jsx and preact
const [value, setValue] = useState(props.initial_value);

return (
<>
<div>
<div>Current value: {value}</div>
<button onClick={() => setValue((v) => v + 1)}>Increment</button>
<NoSSRProps some_client_value={"i was passed in the browser"}/>
</div>
</>
);
}

fn main() {
std::web::HttpServer::new(.verbose)
.serve_component("/counter", Counter({initial_value: 30}))
.serve_component("/no_props", NoPropsAtAll({}))
.listen(":8080");
}

Server Side Rendering

src/strings.duck
template Simple() duckx {
const html_stuff = <div>I am html inside a variable</div>;
html_stuff
}

fn give_me_a_value() -> Int {
13
}

component Counter(props: { initial_value: Int }) jsx {
// Write this component using jsx and preact
const [value, setValue] = useState(props.initial_value);

return (
<>
<div>
<div>Current value: {value}</div>
<button onClick={() => setValue((v) => v + 1)}>Increment</button>
</div>
</>
);
}

template SSRWithParam(props: { color: String, text: String }) duckx {
<div style="color: {props.color}">{props.text}</div>
}

template FullPage(props: { values: Int[] }) duckx {
<>
<!DOCTYPE html>
<html lang="en">
<head>
<title>My page written in Duck SSR</title>
<meta charset="utf-8"/>
</head>
<body>
<Simple/>
<Counter initial_value={54}/>
<SSRWithParam color={"green"} text={"green text"}/>
{
const z = give_me_a_value();
<p>I am a computed html. z: {z}</p>
}

<ul>
{*props.values.iter().map(fn(e: &Int) -> Html { <li>{*e}</li> }).into_list().as_ref()}
</ul>
</body>
</html>
</>
}

fn main() {
std::web::HttpServer::new(.verbose)
.serve_template("/", FullPage({values: [10, 123, 45]}))
.listen(":8080");
}