Yew: Wrong DOM node is changed/removed

Created on 24 Jan 2020  路  9Comments  路  Source: yewstack/yew

Problem
Wrong DOM node is changed/removed

Steps To Reproduce
Steps to reproduce the behavior:

  1. Clone https://github.com/cundd/yew-list-problem
  2. Run cargo web start
  3. Click "Add Song 1 to list!"
  4. Click "Add Song 2 to list!"
  5. Click "Add Song 3 to list!"
  6. Click "Add Song 4 to list!"
  7. Click "Remove Song 1 from list!"
  8. Last node is removed from list

Expected behavior
"Song 1" is removed from setlist

Screenshots
Bad state

Environment:

  • Yew version master
  • Rust version 1.40.0
  • OS: macos
  • Browser chrome, safari, firefox

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

Possibly related to #604

All 9 comments

Something is with your list.rs / view method.
If I change it to the following one, it works properly:

fn view(&self) -> Html {
        html! {
            <p>
                { self.props.songs.iter().map(|s: &Song| html! {<>{s.id()} <br/></>}).collect::<Html>()}
            </p>
        }
    }

Using the same component to render, and if I add change method to list_item, it works but there is still a warning message about vnode not found to remove.

fn change(&mut self, props: Self::Properties) -> ShouldRender {
        self.props = props;
        true
    }

Ah. Looks like it's my fault.

For me it wasn't clear that the ListItem will be repurposed to display new properties.

Although I didn't RTFM, this may be a bit misleading if someone stumbles upon this:

Called when the component's parent component re-renders and the
component's place in the DOM tree remains unchanged.
From yew/src/html/mod.rs:42

From an UI view the place of ListItem+Song1 did change. Although from the view of the implementation it correctly didn't.

May I ask why self.props = props; isn't the default change() behaviour?

I am also new to Yew, just tried to help you out with the implementation, but I have no idea how things work in it. I was thinking the same, it's strange to implement change to the ListItem, as the props of it - in this case - does not change at all, as the whole list is going to re-render.

So I found a way how it works, but I really don't understand why it is a solution and anyway why this behavior exists.

Anybody from Yew contributors? @DenisKolodin ?

@mezeipetister you helped me a lot!

Yeah, agreed that it's too easy to make the mistake. There are a few ways to tackle this:

  1. Not having components manage props themselves. There's a proposal here: https://github.com/yewstack/yew/issues/830
  2. Removing the default implementation of the change method in the Component trait to force implementation

@jstarry so right now, a solution can be to implement change method to all the components?

@mezeipetister right now, change method is implemented here: https://github.com/yewstack/yew/blob/master/src/html/mod.rs#L48

It's not a good default behaviour

Was this page helpful?
0 / 5 - 0 ratings

Related issues

thienpow picture thienpow  路  3Comments

zethra picture zethra  路  5Comments

Boscop picture Boscop  路  5Comments

nixpulvis picture nixpulvis  路  4Comments

kellytk picture kellytk  路  4Comments