DioxusLabs/dioxus
在 GitHub 查看State management with dynamic rendering inside contenteditable divs
Open
#1,962 建立於 2024年2月22日
bughelp wanted
描述
State isn't synced properly when user deletes children nodes in contentetitable div
the user can delete elements by using the backspace inside contentetitable elements. Video below.
I also have a question regarding the event listeners of the child elements. Why they aren't triggered at all? Only the parent element event listeners are called.
Steps To Reproduce
Code:
#![allow(non_snake_case)]
// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
use dioxus::prelude::*;
use dioxus_desktop::{tao::event_loop::EventLoop, use_window, LogicalSize, WindowBuilder};
use uuid::Uuid;
fn main() {
// launch the dioxus app in a webview
dioxus_desktop::launch_cfg(
App,
dioxus_desktop::Config::new()
.with_custom_head(
r#"
<head>
<link rel="stylesheet" href="public/tailwind.css">
</head>
"#
.to_string(),
)
.with_window(
WindowBuilder::new()
.with_title("Desktop App")
.with_inner_size(LogicalSize {
width: 400.0,
height: 400.0,
})
.with_min_inner_size(LogicalSize {
width: 400.0,
height: 400.0,
})
.with_transparent(true),
),
)
}
enum Blocks {
ParagraphBlock(Uuid)
}
pub fn Paragraph(cx: Scope) -> Element {
let inner_text = use_state(cx, || "".to_string());
cx.render(rsx! {
div {
class: "border-solid border-2 border-indigo-300 p-4 rounded-lg some-block",
onkeydown: move |e| {println!("Inner State (onkeydown) {:?}", e.key().to_string());},
oninput : move |e| {println!("Inner State (oninput) {:?}", e.data.value.clone()); inner_text.set(e.data.value.clone())},
p{
class: "text-xs font-semibold text-gray-600 uppercase some-block-header",
"contenteditable": "false",
"Paragraph"
},
p {
class: "text-base text-gray-800 empty:before:content-[attr(data-placeholder)] empty:before:text-gray-300 whitespace-pre-wrap selectable-area",
"data-placeholder" : "Write text here ..",
inner_text.as_str()
}
}
}
)
}
fn App(cx: Scope) -> Element {
let window = use_window(&cx);
let some_blocks = use_ref(cx, Vec::<Blocks>::new);
if some_blocks.read().is_empty() {
some_blocks
.write()
.push(Blocks::ParagraphBlock(Uuid::new_v4()));
some_blocks
.write()
.push(Blocks::ParagraphBlock(Uuid::new_v4()));
some_blocks
.write()
.push(Blocks::ParagraphBlock(Uuid::new_v4()));
}
let binding = some_blocks.read();
let blocks_rendered = binding
.iter()
.map(|block| match block {
Blocks::ParagraphBlock(id) => rsx! {Paragraph{key: "{id}"}},
});
cx.render(rsx! {
div {
class: "h-screen w-screen flex bg-pink-100 p-4 rounded-lg flex-col space-y-4 overflow-auto",
"contenteditable" : "true",
onkeydown: move |_e| { println!("Number of blocks: {:?} ", some_blocks.read().len()) },
onmousedown: move |_| {window.drag()},
blocks_rendered
}
})
}
Expected behavior
State should be maintained and synced
Screenshots
Environment:
- Dioxus version: 0.4.3
- Rust version: rustc 1.76.0
- OS info: Windows 10
- App platform: desktop
Questionnaire
- I'm interested in fixing this myself but don't know where to start
- I would like to fix and I have a solution
- I don't have time to fix this right now, but maybe later