Take anything that implements Hash for keys - #5687
Open
DominicBurkart wants to merge 1 commit into
Open
Conversation
Keys in rsx were restricted to formatted strings, forcing hashable
types like Uuid through a wasteful value -> String -> diff path.
Introduce dioxus_core::Key with two variants: Key::Str for formatted
string keys (still rewritable by hot reloading from the literal pool)
and Key::Hashed for keys built from the hash of any value implementing
Hash. VNodeInner::key is now Option<Key> and keyed diffing compares
Key values directly instead of &str.
In the rsx macro, key: "{value}" keeps its existing string path,
while any other expression (key: uuid, key: item.id) is accepted and
hashed at the call site via Key::hashed. HotReloadedTemplate::key
becomes Option<HotReloadKey>, where HotReloadKey::Dynamic marks an
expression key computed at the call site: hot reloading keeps working
for templates with expression keys as long as the key expression
itself is unchanged, and falls back to a full rebuild when it changes.
This also fixes non-string literal keys like key: 1 silently producing
Some("1") in release but None in debug: they now go through the
hashed path consistently in both modes.
Closes DioxusLabs#2188
DominicBurkart
marked this pull request as ready for review
July 20, 2026 20:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2188
Keys in rsx were restricted to formatted strings, so a hashable id like a
Uuidhad to take the wastefulUuid -> String -> diffpath. This PR letskeyaccept any expression whose value implementsHash:How it works
dioxus_core::Keyis a new enum with two variants:Key::Str(String)for formatted-string keys (unchanged behavior, still rewritable by hot reloading from the literal pool) andKey::Hashed(u64)for keys built by hashing anyHashvalue with a deterministicDefaultHasher.VNodeInner::keyis nowOption<Key>, and keyed diffing compares/hashesKeyvalues directly instead of&str.key: "{value}"keeps its existing path. Any other expression (key: uuid,key: item.id, shorthandkey) is now accepted byvalidate_key(which previously carried atodopointing at exactly this issue) and is hashed at the call site viaKey::hashed(&(expr)). Static keys are still rejected. Event handlers / if-chains as keys are still rejected.HotReloadedTemplate::keybecomesOption<HotReloadKey>whereHotReloadKey::Fmtedre-renders from the literal pool as before, andHotReloadKey::Dynamicmarks an expression key computed at the rsx call site (the codegen now passes the call-site key intoDynamicValuePool::render_with). The hot-reload differ remembers the last build's key expression: templates with an unchanged expression key stay hot-reloadable; changing the key expression falls back to a full rebuild.Notes
Key::from("a") != Key::hashed("a"). Since every instance of a template site generates its keys the same way, this doesn't affect diffing in practice.key: 1silently compiled toSome("1")in release butNonein debug: literals now go through the hashed path consistently in both modes.Key::Hashedcompares 64-bit hashes rather than values, so a collision between two sibling keys is theoretically possible (~2⁻⁶⁴, SipHash). Happy to switch to storing/comparing something stronger if that tradeoff isn't acceptable.Keyis exported fromdioxus_corebut intentionally not added todioxus::prelude, which already re-exports the keyboardKeytype fromdioxus_html.Testing
packages/core/tests/diff_hashed_keys.rs: keyed-diff scenarios mirrored fromdiff_keyed_list.rsusing integer keys, a custom#[derive(Hash)]type, component keys, and a stability check — asserting the same mutations as their string-key equivalents.packages/rsx-hotreload/tests/hotreload_pattern.rs::expr_keys: expression keys hot reload when unchanged, require rebuild when changed/added/switched from a formatted key, and can be removed.packages/rsx/tests/parsing.rs: expression keys parse without diagnostics; event-handler keys still error. The oldkey_must_be_formattedcontract test is replaced since this PR intentionally changes that contract.cargo testfordioxus-core(incl. doctests),dioxus-rsx,dioxus-rsx-hotreloadall pass;cargo clippy -D warningsclean on the three touched crates.https://claude.ai/code/session_01PWiGWxtiybnBJYQBHYYcmQ