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 thanExtension
to passLeptosOptions
. 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 intostable
, to requiring an opt-in fornightly
features. Click here to see a diff with the necessary changes.- If you're using
stable
, remove thestable
feature (it's now the default.) - If you're using
nightly
, add thenightly
feature toleptos
,leptos_router
, andleptos_meta
- If you're using
leptos
no longer defaults tocsr
, but is opt-in.- If you're using CSR, add the
csr
feature toleptos
(same asleptos_router
andleptos_meta
- If you're using SSR/hydration, you can remove most
default-features = false
on Leptos dependencies, as that mainly served to disable the defaultcsr
feature, which is no longer enabled by default.
- If you're using CSR, add the
ServerFnError
no longer implementsstd::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 toclass
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 fromsearch
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()
andupdate()
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 loadingasync
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 avoidScope
issues (closes #1231) by @gbj in #1232 - feat: add an
anyhow
-likeResult
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
andcsr
features rather thanstable
anddefault-features = false
by @gbj in #1227 - fix: add missing attribute-escaping logic in
leptos_meta
andclass
attributes in SSR (closes #1238) by @gbj in #1241 - fix(counters_stable): intermittent closed target errors (#1240) by @agilarity in #1243
New Contributors
- @kasbuunk made their first contribution in #1050
- @vldm made their first contribution in #1054
- @Skyliegirl33 made their first contribution in #1080
- @genusistimelord made their first contribution in #1090
- @anacrolix made their first contribution in #1096
- @abhikjain360 made their first contribution in #1102
- @maccesch made their first contribution in #1105
- @tempbottle made their first contribution in #1129
- @Lun4Red made their first contribution in #1141
- @itehax made their first contribution in #1111
- @PaulWagener made their first contribution in #1165
- @funlennysub made their first contribution in #1109
- @devriesp made their first contribution in #1172
- @hchockarprasad made their first contribution in #1183
- @lalanikarim made their first contribution in #1175
- @MolotovCherry made their first contribution in #1200
- @tguichaoua made their first contribution in #1208
- @tysen made their first contribution in #1217
Full Changelog: v0.3.0...v0.4.0