Mikael Hadler
I am a Software Developer, love opensource and share experiences with the local community
Fast Web Development in Rust
Leptos is a full-stack, isomorphic Rust web framework leveraging fine-grained reactivity to build declarative user interfaces.
Leptos can be used to build apps in three different ways:
This includes support for HTTP streaming and HTML
Leptos provides primitives to write isomorphic server functions, i.e., functions that can be called with the “same shape” on the client or server, but only run on the server without needing to create and maintain a separate REST or other API.
Leptos is built on the Web platform and Web standards. The router is designed to use Web fundamentals (like links and forms)
The entire framework is built from reactive primitives. This allows for extremely performant code with minimal overhead: when a reactive signal’s value changes, it can update a single text node, toggle a single class, or remove an element from the DOM without any other code running. (So, no virtual DOM overhead!)
Tell Leptos how you want the page to look, and let the framework tell the browser how to do it.
use leptos::*;
#[component]
fn App(cx: Scope) -> impl IntoView {
let (count, set_count) = create_signal(cx, 0);
// the `view` macro is how we define the user interface
// it uses an HTML-like format that can accept certain Rust values
view! { cx,
<button
on:click=move |_| {
set_count.update(|n| *n += 1);
}
>
"Click me"
</button>
<p>
<strong>"Reactive: "</strong>
{move || count.get()}
</p>
<p>
<strong>"Reactive shorthand: "</strong>
// signals are functions, so we can remove the wrapping closure
{count}
</p>
<p>
<strong>"Not reactive: "</strong>
// NOTE: if you write {count()}, this will *not* be reactive
// it simply gets the value of count once
{count()}
</p>
}
}
fn main() {
leptos::mount_to_body(|cx| view! { cx, <App/> })
}
To document a component and its props, you can simply add doc comments on the component function, and each one of the props
/// Shows progress toward a goal.
#[component]
fn ProgressBar(
cx: Scope,
/// The maximum value of the progress bar.
#[prop(default = 100)]
max: u16,
/// How much progress should be displayed.
#[prop(into)]
progress: Signal<i32>,
) -> impl IntoView {
/* ... */
}These comments
Generate this
use leptos::*;
use leptos_router::*;
#[component]
pub fn App(cx: Scope) -> impl IntoView {
view! {
<Router>
<nav>
/* ... */
</nav>
<main>
// all our routes will appear inside <main>
<Routes>
<Routes>
<Route path="/" view=|cx| view! { cx, <Home/> }/>
<Route path="/users" view=|cx| view! { cx, <Users/> }/>
<Route path="/users/:id" view=|cx| view! { cx, <UserProfile/> }/>
<Route path="/*any" view=|cx| view! { cx, <NotFound/> }/>
</Routes>
</Routes>
</main>
</Router>
}
}
...
#[server(GetPost, "/api")]
pub async fn get_post(id: usize) -> Result<Option<Post>, ServerFnError> {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
Ok(POSTS.iter().find(|post| post.id == id).cloned())
}
By Mikael Hadler
I am a Software Developer, love opensource and share experiences with the local community