DioxusLabs/dioxus

State management with dynamic rendering inside contenteditable divs

Aberta

#1.962 aberto em 22 de fev. de 2024

 (4 comentários) (0 reação) (0 responsável)Rust (1.655 forks)batch import
bughelp wanted

Métricas do repositório

Stars
 (36.038 estrelas)
Métricas de merge de PR
 (Mesclagem média 16d 13h) (9 fundiu PRs em 30d)

Description

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

dioxus-bug

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

Guia do colaborador