Skip to content

Plea for help regarding hydration and dispose panics #4540

@lukexor

Description

@lukexor

This is a desperate plea for help on some sort of solution for working with or around hydration and signal use-after-dispose panics.

First, let me say that Leptos and signal-based rendering to date has been a phenomenal game-changer for our team and our product development. In many ways it is such a superior experience both of terms of DC and I'm performance. But in terms of error handling and debug introspection, it still has a ways to go.

While I understand some of the nuances for why Rust, as a systems language, opts for panicking as a form of error handling when invariants are violated, there are use cases where panicking is not acceptable in a production environment. As evident by the push in the Rust-for-Linux project to add alternative APIs for code paths that normally panic (e.g. Vec::push when it fails to allocate). See rust-lang/rust#48043

For web development, at the opposite end of the stack the general paradigm follows the Robustness principal (https://en.wikipedia.org/wiki/Robustness_principle): "be conservative in what you do, be liberal in what you accept from others"

For example, HTML will take almost anything you throw at it and still render something. It doesn't just crash. Similarly, JavaScript will throw errors into the console and stop running the current function but the event loop will still keep going processing other code.

One example where this difference in paradigms got me recently was in accidentally nesting a button element inside another (I didn't realize thaw table headers added a button wrapper). Worked fine in development but in release for some reason, the browser converted the HTML to siblings instead of parent/child resulting in taking down the whole page due to a hydration error. This sort of problem is not a reason (imo) to crash the page and make it unresponsive. I at least have a panic handler that displays an error and a refresh the page link, but it's not a good solution.

Similarly, I've had issues with thaw's class list handling where it's using disposed signals upon page navigation. This would only affect styling in the worst case (assuming it's observable at all) and is also not a reason to crash the page. (I'm not trying to pick on thaw here, it's been great to bootstrap a UI with, I've had similar problems with leptos-use).

It's been extremely frustrating keeping up with the constant changes where one version works, and then panics after an upgrade, or a co-worker adds an innocent looking feature and it only starts panicking on release.

While leptos does have many try_ methods for signals, they do not help with hydration errors, nor do they help in cases where the signal access is inside a dependency like thaw or leptos-use. Solving it involves submitting an upstream PR and waiting for it to be merged and released, or to fork and alter the problematic code paths to use non-panicking apis which can be a prohibitive maintenance burden.

Another option, which I'd prefer, is opt-in, and backwards-compatible is a feature flag or other runtime setting that treats panic cases more like HTML handling bad syntax by just doing the slightly wrong thing or the best thing it can.

For systems programming, I understand wanting to fail fast rather than doing the wrong thing, especially when it involves potential data corruption, but for displaying a web page, especially when it's not doing something in response to a user action, having it shown slightly wrong but still functional is more preferable. If it's mission critical for it to display exactly right or crash, to avoid misinforming a user, maybe some API that can opt into strict hydration or something is a better route.

I'm sure I'm missing some nuance in this request or not considering all the ramifications, but I'd like to start brainstorming some sort of solution short of removing thaw and leptos-use entirely in order to fully control the stack to avoid panicking code paths. I'd be happy to dedicate some time to contributing if a direction can be agreed upon.

Thanks again to the entire leptos community for all the amazing work bring Rust into the web stack.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions