cargo leptos 0.4.0
`v0.4.0`

latest releases: 0.7.0-preview2, 0.7.0-preview, 0.6.11...
14 months ago

v0.4.0

Enough bugfixes and features have accumulated in the main branch that it's time for a new release. However, a very early change meant this needs to be a semver bump. Rather than continuing the confusion of the feature/bug gap between 0.3.1 and main, this releases the current state of the main branch.

I was actually surprised, putting together these release notes, how much good stuff there is in here that I'd forgotten was new to this release!

This does not include the reactive ownership rewrite (#918), which I'd guess will be 0.5. But it does include the following...

Breaking Changes

  • leptos_axum now uses the (more common, more type-safe, more extensible) State and sub-state patterns rather than Extension to pass LeptosOptions. This will require a few small but key changes to apps uses Axum migrating from 0.3.x to 0.4.0. Click here to see a diff with the necessary changes.
  • Switch from defaulting to nightly and opting into stable, to requiring an opt-in for nightly features. Click here to see a diff with the necessary changes.
    • If you're using stable, remove the stable feature (it's now the default.)
    • If you're using nightly, add the nightly feature to leptos, leptos_router, and leptos_meta
  • leptos no longer defaults to csr, but is opt-in.
    • If you're using CSR, add the csr feature to leptos (same as leptos_router and leptos_meta
    • If you're using SSR/hydration, you can remove most default-features = false on Leptos dependencies, as that mainly served to disable the default csr feature, which is no longer enabled by default.
  • ServerFnError no longer implements std::error::Error (see below). ServerFnErrorErr does, if that's needed.
  • The children of a <Suspense/> or <Transition/> are now rendered once, then subsequently cloned. If you are reading resources reactively (move || data.read(cx)) they should continue to update reactively. If you are reading resources non-reactively (<div>{resource.read(cx)}</div>) this would have worked previously, and now will not be reactive.

Features

Automatic Server Function Registration

Server functions no longer need to be registered (except on exotic platforms like server-side WASM). Instead, they are registered automatically, making it even easier to define and use them.

Axum Extractor Support

You can now use Axum extractors directly in server functions.

#[server(QueryExtract, "/api")]
pub async fn query_extract(cx: Scope) -> Result<String, ServerFnError> {
    use axum::{extract::Query, http::Method};
    use leptos_axum::extract;

    extract(cx, |method: Method, res: Query<MyQuery>| async move {
            format!("{method:?} and {}", res.q)
        },
    )
    .await
    .map_err(|_| ServerFnError::ServerError("Error with server extractor".into()))
}

Improved Error Handling

Leptos now provides a leptos::error::Result type that behaves much like anyhow::Result (i.e., other errors can be converted into it using ?) but can be rendered directly in the view and caught by <ErrorBoundary/>. ServerFnError can also handle conversion from any error, making errors in server functions easier to handle.

use leptos::error::Result;

async fn fetch_cats(count: CatCount) -> Result<Vec<String>> {
    if count > 0 {
        // make the request
        let res = reqwasm::http::Request::get(&format!(
            "https://api.thecatapi.com/v1/images/search?limit={count}",
        ))
        .send()
        .await?
        // convert it to JSON
        .json::<Vec<Cat>>()
        .await?
        // extract the URL field for each cat
        .into_iter()
        .take(count)
        .map(|cat| cat.url)
        .collect::<Vec<_>>();
        Ok(res)
    } else {
        Err(CatError::NonZeroCats.into())
    }
}

#[server(AddTodo, "/api")]
pub async fn add_todo(title: String) -> Result<(), ServerFnError> {
    let mut conn = db().await?;

    Ok(
        sqlx::query("INSERT INTO todos (title, completed) VALUES ($1, false)")
            .bind(title)
            .execute(&mut conn)
            .await
            .map(|_| ())?,
    )
}

Async Routing

While routing, optionally wait for the next route to load before navigating, approximating the behavior of a multi-page app more closely, by using the set_is_pending prop on <Router/> and the <RoutingProgress/> component. (See #1055.)

#[component]
pub fn App(cx: Scope) -> impl IntoView {
    let (is_routing, set_is_routing) = create_signal(cx, false);

    view! { cx,
        <Router set_is_routing> // will wait for async data on next page to load before navigating
Screen.Recording.2023-05-20.at.9.34.42.PM.mov

<Await/>

The new <Await/> component improves the ergonomics of loading async blocks.

async fn fetch_monkeys(monkey: i32) -> i32 {
  // do some expensive work
  3
}

view! { cx,
	<Await
        future=|cx| fetch_monkeys(3)
        bind:data // see below for bind:
    >
        <p>{*data} " little monkeys, jumping on the bed."</p>
    </Await>
}

bind: syntax on components and slots

The children prop currently only supports one argument, the Scope. It's sometimes useful to be able to pass additional arguments to be used in children, but they need to be named. bind: allows you to define a children prop that takes additional arguments and name them. For example, the <Await/> component (see above) is defined like this

pub fn Await<T, Fut, FF, VF, V>(
	/* ... other props */
    children: VF,
) -> impl IntoView
where
    /* ... other generics */
    VF: Fn(Scope, &T) -> V + 'static,

The identifier for this second &T argument is then given with bind:{ident} (again, see above.)

Other Features

  • Rewritten and less-buggy <For/> implementation.
  • Specify exact server function paths with a fourth argument, rather than the hashed path used by default to avoid name collisions
#[server(MyServerFnType, "/api-prefix", "Url", "hello")] // will be at `/api-prefix/hello`
  • Significant reductions in overhead of hydration keys, and therefore in SSR performance.
  • Improvements to recoverability, error handling, and syntax highlighting in the view macro.

Full Changelog

  • fix: typo in actix extract documentation by @markcatley in #1043
  • fix: <Suspense/> hydration when no resources are read under it by @gbj in #1046
  • docs: fix small docs issues (closes #1045) by @gbj in #1049
  • docs: fix typo in view fn by @kasbuunk in #1050
  • Update lib.rs by @sjud in #1053
  • fix: multipart forms on server fns by @yuuma03 in #1048
  • tests: fix broken SSR doctests by @gbj in #1056
  • fix: todomvc example style errors by @agilarity in #1058
  • Added Debug, PartialEq and Eq derives to trigger. by @dgsantana in #1060
  • examples: fix todo_app_sqlite_axum by @gbj in #1064
  • test: verify tailwind example with playwright tests by @agilarity in #1062
  • fix: docs note on style refers to class by @gbj in #1066
  • docs: update notes on WASM binary size to work with SSR too (closes #1059) by @gbj in #1068
  • docs: clarify SSR/WASM binary size comments by @gbj in #1070
  • Specify Server Fn Paths by @benwis in #1069
  • test: setup e2e automatically for tailwind example by @agilarity in #1067
  • Rsx parser with recovery after errors, and unquoted text by @vldm in #1054
  • feat: add "async routing" feature by @gbj in #1055
  • fix/change: remove ? prefix from search in browser (matching server behavior) - closes #1071 by @gbj in #1077
  • fix: debug-mode bugs in <For/> (closes #955, #1075, #1076) by @gbj in #1078
  • docs: clarify difference between set() and update() by @gbj in #1082
  • feat: manually implement Debug, PartialEq, Eq and Hash for reactive types by @Skyliegirl33 in #1080
  • fix: correctly handle new navigations while in the middle of an async navigation by @gbj in #1084
  • Docs edit: added a hint for a common error when using use_navigate by @sjud in #1063
  • Remove LeptosProvider trait and use Axum SubStates by @benwis in #1085
  • fix: missing ? in navigation now that it is removed on browser side to match server by @gbj in #1092
  • feat: add <Await/> component to improve ergonomics of loading async blocks by @gbj in #1091
  • updated axum_database_sessions to axum_session. by @genusistimelord in #1090
  • Improve fetch example by @anacrolix in #1096
  • fix: duplicate headers (like Set-Cookie) on the actix integration by @yuuma03 in #1086
  • feat: add Axum extract() function by @gbj in #1093
  • docs: fix generic type by @abhikjain360 in #1102
  • Docs: updates by @gbj in #1104
  • fix: remove debug logs accidentally included by @gbj in #1106
  • Fix: make template macro independent. by @vldm in #1101
  • examples: fix suspense scope in ssr_modes_axum by @gbj in #1107
  • added scrollend event by @maccesch in #1105
  • fix: dispose of runtime when stream is actually finished (closes #1097) by @gbj in #1110
  • fix(examples): verification errors (#1113) by @agilarity in #1115
  • build(examples): auto install playwright browsers (#1112) by @agilarity in #1114
  • docs: add examples of synchronizing signal values by @gbj in #1121
  • chore: fix warnings by @gbj in #1123
  • build: use cargo's sparse registry protocol by @gbj in #1127
  • chore: add issue templates by @gbj in #1128
  • perf: reduce overhead of hydration keys by @gbj in #1122
  • chore: add guide for contributors by @gbj in #1131
  • Closing tag highlight/hower and go-to definition support in lsp. by @vldm in #1126
  • ci(examples): verify examples by @agilarity in #1125
  • work around for remove inline0.js by @tempbottle in #1129
  • fix: remove nested fragments from Suspense (closes #1094 and #960) by @gbj in #1135
  • fix: wait for blocking fragments to resolve before pulling metadata (closes #1118) by @gbj in #1137
  • Ran cargo clippy --fix. by @martinfrances107 in #1136
  • feat: variable bindings on components and slots by @yuuma03 in #1140
  • Update 16_routes.md by @Lun4Red in #1141
  • Examples: Tailwind + Leptos & Axum by @itehax in #1111
  • fix: erroneous reactivity warning at form.rs:96 by @gbj in #1142
  • fix queue_microtask by @dgsantana in #1145
  • feat: pass components with no props directly into the view as a function that takes only Scope by @gbj in #1144
  • docs: add sections on progressive enhancement/graceful degradation and <ActionForm/> by @gbj in #1151
  • fix: handle external redirects correctly in <ActionForm/> by @gbj in #1160
  • feat: enable bind: syntax for <Await/> component by @gbj in #1158
  • fix: pass through docs for server functions (closes #1163) by @gbj in #1164
  • Replace preempted with version in Resource by @PaulWagener in #1165
  • feat: clone children instead of calling again (closes #398) by @gbj in #1157
  • Initial fix for #949 + #1023 by @funlennysub in #1109
  • feat: register server functions automatically by @gbj in #1154
  • For algo v2 by @jquesada2016 in #1146
  • actix: Removed calls to .collect() and .into_ier() by @martinfrances107 in #1133
  • Fix grammar in signals doc. by @devriesp in #1172
  • Replace ouroboros with self_cell by @novacrazy in #1171
  • Since rust 1.70 - the warnings about have gotten more particular. by @martinfrances107 in #1174
  • fixed removes being wrong and leading to panics sometimes by @jquesada2016 in #1173
  • docs: clarify available server fn encodings by @gbj in #1178
  • docs: fix failing doctests from server fn docs by @gbj in #1179
  • fix: <ErrorBoundary/> IDs with new hydration key system by @gbj in #1180
  • ci(examples): split jobs and verify changed examples by @agilarity in #1155
  • chore: criterion was outdated version 0.4.0 becomes 0.5.1. by @martinfrances107 in #1184
  • Chore: router -- cached is outdated was 0.43.0 is now 0.44.0. by @martinfrances107 in #1187
  • fixed bug when clearing which ignores further additions by @jquesada2016 in #1181
  • ci(examples): include all example projects by @agilarity in #1188
  • fix(examples/js-framework-benchmark): error: cannot find macro template in this scope (#1182) by @agilarity in #1189
  • Use config for serde_qs deserialization by @hchockarprasad in #1183
  • fix: allow FnOnce extractors by @gbj in #1192
  • fix: setting set_pending now that <Transition/> body doesn't re-render by @gbj in #1193
  • [documentation] Renamed function names in 13-actions chapter of book to reduce confusion by @lalanikarim in #1175
  • Removed clippy warnings - merged "if"s by @martinfrances107 in #1190
  • Reorder <For /> apply_diff steps by @jquesada2016 in #1196
  • ci(examples): split check example and improve workflows by @agilarity in #1191
  • fix: animations on multiple back navigations (closes #1088) by @gbj in #1204
  • fix: SVG <use> in SSR by @gbj in #1203
  • ci(examples): automatically keep the list of example projects current by @agilarity in #1198
  • Fix #1199 - Docs: Add note on how to fix failing builds which rebuild-std by @MolotovCherry in #1200
  • build(examples): generate workspace members variable by @agilarity in #1201
  • doc(working_with_signals): fix typo by @tguichaoua in #1208
  • fix: don't re-mount identical child in DynChild by @gbj in #1211
  • docs: a few grammar fixes, removal of ref to ComponentProps by @tysen in #1217
  • examples: update leptos-tailwind-axum to use main branch by @gbj in #1218
  • fix(examples/tailwind): host system is missing dependencies to run browsers by @agilarity in #1216
  • fix: memo with_untracked by @lpotthast in #1213
  • docs: document <ErrorBoundary/>/<Suspense/> relationship by @gbj in #1210
  • Fix <For /> panic when clearing by @jquesada2016 in #1220
  • fix: nested Suspense/Transition with cascading resources by @gbj in #1214
  • feat: improved error handling and version tracking for pending actions/<ActionForm/> (closes #1205) by @gbj in #1225
  • fix: make <Transition/> transparent like <Suspense/> to avoid Scope issues (closes #1231) by @gbj in #1232
  • feat: add an anyhow-like Result type for easier error handling by @gbj in #1228
  • docs: typo in "Parent-Child Communication" by @gbj in #1237
  • test(counters_stable): add playwright tests by @agilarity in #1235
  • change: migrate to nightly and csr features rather than stable and default-features = false by @gbj in #1227
  • fix: add missing attribute-escaping logic in leptos_meta and class attributes in SSR (closes #1238) by @gbj in #1241
  • fix(counters_stable): intermittent closed target errors (#1240) by @agilarity in #1243

New Contributors

Full Changelog: v0.3.0...v0.4.0

Don't miss a new leptos release

NewReleases is sending notifications on new releases.