Giter Club home page Giter Club logo

Comments (6)

ivanceras avatar ivanceras commented on May 16, 2024

Thank you @vwpix for a very detailed report on the issue. We will be working on this.

from sauron.

ivanceras avatar ivanceras commented on May 16, 2024

So, after some fiddling I realize that this is one of the case where the DOM diffing fails.
The code which deals with diffing elements in the DOM by comparing their attributes and event listener to see if the element can be reused or not. In rust, 2 closures are not equal even if they have the same exact code. This is not suitable for the dom-diffing algorithm as we want to be able to re-use the elements as much as possible otherwise, it will re-create the element for each view call which would makes the whole system very sluggish.
That said, we try to compare closures based only on their function signatures, in order to aggressively match old elements to new elements as much as possible.

This will be the behavior of the framework for now, while I haven't found a better way to solution. For now, you can use the work around to mark the element with replace(true) which instruct the diffing algorithm to re-create the element at every view call.

        let buttons = self
            .nodes
            .iter()
            .map(|&x| {
                button(
                    [
                        id(format!("btn_{}", x)),
                        replace(true),
                        on_click(move |_| Msg::ClickNode(x)),
                    ],
                    [text(x)],
                )
            })
            .collect::<Vec<_>>();

from sauron.

ivanceras avatar ivanceras commented on May 16, 2024

Also, I couldn't re-create the crash error: closure invoked recursively in any browser: firefox,chrome,webkit. I'm on linux.

Hint: you can rewrite your view like this to make it cleaner.

   fn view(&self) -> Node<Msg> {
        div(
            [],
            [
                text(&self.last),
                button(
                    [on_click(|_| Msg::InsertNode)],
                    [text("add item (broken)")],
                ),
                button(
                    [on_click(|_| Msg::AddNode)],
                    [text("add item (working)")],
                ),
                div(
                    [id("buttons")],
                    self.nodes.iter().map(|&x| {
                        button(
                            [
                                id(format!("btn_{}", x)),
                                replace(true),
                                on_click(move |_| Msg::ClickNode(x)),
                            ],
                            [text(x)],
                        )
                    }),
                ),
            ],
        )
    }

from sauron.

vwpix avatar vwpix commented on May 16, 2024

thank u for looking into it, and the workaround tip will be useful for now

Also, I couldn't re-create the crash error: closure invoked recursively in any browser: firefox,chrome,webkit. I'm on linux.

the crash show up if i add the "key(x)" attribute to the generated buttons , tested in latest firefox nightly and chromium

edit:
now i found another (related) bug, if i use "replace" combined with "key", it shows the same crash but the broken buttons don't get added, and it breaks the entire app after that
using replace alone works fine

from sauron.

ivanceras avatar ivanceras commented on May 16, 2024

After hours of hard-work revising and improving the diffing algorithm for keyed elements and tracking down the bug for the closure invoked recursively or destroyed already error, this issue is now solved.

I created a repo for issues like this, which contain the actual code for the use-case.

Thank you @vwpix again, for filing this issue, this has solved multiple long-standing bug in sauron and in mt-dom code.

from sauron.

ivanceras avatar ivanceras commented on May 16, 2024

crate version where this is fixed:

  • sauron 0.49.2
  • mt-dom 0.19.0

from sauron.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.