raphlinus / crochet

Explorations in reactive UI patterns
Apache License 2.0
367 stars 21 forks source link

List example select lags one frame #5

Closed tbelaire closed 3 years ago

tbelaire commented 4 years ago

When you click on a button in the list example

         self.list_view
            .run(cx, &self.data, |cx, mut is_selected, id: Id, item| {
                Row::new().build(cx, |cx| {
                    if Button::new("Select").build(cx) {
                        new_sel = Some(id);
                        is_selected = true;
                    }
                    let sel_str = if is_selected { "[*]" } else { "[ ]" };
                    Label::new(format!("{} {}", sel_str, item)).build(cx);
                });
            });
        if let Some(id) = new_sel {
            self.list_view.select(id);
        }

This doesn't set is_selected until the next time through the loop, and if you don't move the mouse, it stays with the wrong selection. You have to double click, or click and move the mouse in order to have it update.

This doesn't happen with the create, delete and update buttons, as they run before the buttons loop.

I don't see a nice way to reach back in the loop and change the label, so is there a way to mark the state as invalid and demand a second run through the run function right away?

raphlinus commented 4 years ago

Thanks for the observation! I'm aware of this, but still mulling the right way to fix it. It's going to involve some rerunning of the app logic until it quiesces, but I haven't figured exactly the right criterion for how many times that should be, and what facilities should be exported to the app to control it. I mean, a badly-behaved app could increment a counter every pass through the event loop and update a label based on that.

I might do something simple, like always running it twice after an event that actually places an action into an action queue, and see how far off that is from the right solution.

Diggsey commented 4 years ago

I would expect the app logic to be rerun any time an action is queued, even if that means running it several times.