Fix hydration with empty spread attributes (#4647)
* Fix hydration of empty spread attributes * add a regression test * fix doctest
This commit is contained in:
1 parent
f48aec7eff
commit
03801e1312
8 files changed
+94
-2
No files matched your search
@@ -819,10 +819,14 @@ impl VNode {
|
||||
}
|
||||
};
|
||||
|
||||
// Write the value for each attribute in the group
|
||||
for attr in &**attribute {
|
||||
self.write_attribute(attribute_path, attr, id, mount, dom, to);
|
||||
dom.set_mounted_dyn_attr(mount, attribute_idx, id);
|
||||
}
|
||||
// Set the mounted dynamic attribute once. This must be set even if no actual
|
||||
// attributes are present so it is present for renderers like fullstack to look
|
||||
// up the position where attributes may be inserted in the future
|
||||
dom.set_mounted_dyn_attr(mount, attribute_idx, id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// @ts-check
|
||||
const { test, expect } = require("@playwright/test");
|
||||
|
||||
test("spread attributes hydrate", async ({ page }) => {
|
||||
await page.goto("http://localhost:7979");
|
||||
|
||||
// Expect the page to contain the button
|
||||
const counter = page.locator("#counter");
|
||||
await expect(counter).toHaveText("Count: 0");
|
||||
// Clicking on the button should increment the count
|
||||
await counter.click();
|
||||
await expect(counter).toHaveText("Count: 1");
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "dioxus-playwright-fullstack-spread-test"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dioxus = { workspace = true, features = ["fullstack"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
server = ["dioxus/server"]
|
||||
web = ["dioxus/web"]
|
||||
@@ -0,0 +1,40 @@
|
||||
//! Regression test for <https://github.com/DioxusLabs/dioxus/issues/4646>
|
||||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
fn main() {
|
||||
dioxus::launch(|| {
|
||||
rsx! {
|
||||
Comp {}
|
||||
Comp {}
|
||||
Button {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Button() -> Element {
|
||||
let mut count = use_signal(|| 0);
|
||||
|
||||
rsx! {
|
||||
button {
|
||||
id: "counter",
|
||||
onclick: move |_| {
|
||||
count += 1;
|
||||
},
|
||||
"Count: {count}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn Comp(#[props(extends = GlobalAttributes)] attributes: Vec<Attribute>) -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
width: 100,
|
||||
div {
|
||||
..attributes,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,15 @@ module.exports = defineConfig({
|
||||
reuseExistingServer: !process.env.CI,
|
||||
stdout: "pipe",
|
||||
},
|
||||
{
|
||||
cwd: path.join(process.cwd(), "fullstack-spread"),
|
||||
command:
|
||||
'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --web --addr "127.0.0.1" --port 7979',
|
||||
port: 7979,
|
||||
timeout: 50 * 60 * 1000,
|
||||
reuseExistingServer: !process.env.CI,
|
||||
stdout: "pipe",
|
||||
},
|
||||
{
|
||||
cwd: path.join(process.cwd(), "fullstack-routing"),
|
||||
command:
|
||||
|
||||
@@ -301,9 +301,12 @@ impl WebsysDom {
|
||||
let id = vnode
|
||||
.mounted_dynamic_attribute(*id, dom)
|
||||
.ok_or(VNodeNotInitialized)?;
|
||||
// We always need to hydrate the node even if the attributes are empty so we have
|
||||
// a mount for the node later. This could be spread attributes that are currently empty,
|
||||
// but will be filled later
|
||||
mounted_id = Some(id);
|
||||
for attribute in attributes {
|
||||
let value = &attribute.value;
|
||||
mounted_id = Some(id);
|
||||
if let AttributeValue::Listener(_) = value {
|
||||
if attribute.name == "onmounted" {
|
||||
to_mount.push(id);
|
||||
|
||||
Reference in new issue
Block a user