4 ms·
> Clicking on buttons will start triggering events which will modify the state in the model that will in turn start triggering event listeners causing your GUI
by MaxBarraclough 6y ago
> Clicking on buttons will start triggering events which will modify the state in the model that will in turn start triggering event listeners causing your GUI to flash like a christmas tree. The problem of data bindings and change listeners is that they make it really easy to introduce a hidden circular event listeners that will trigger one another multiple times (event A changes state B and change of state B triggers event A).
Agree with both of these points. You can no longer treat assignment simply as the way you mutate data, you also have to anticipate its effects in the data-binding system.
I imagine the circular event problem could be addressed with static analysis, but I don't know of any framework that does this.
- amelius 6y agoIsn't this what React and precursors were invented for?
- MaxBarraclough 6y agoI have to plead ignorance here. Does it have a way of detecting circular events?
- amelius 6y agoThe idea is to separate the state of the application from the presentation, which in practice leads to not having circular dependencies in the first place. And you can update the display after all changes are finished, so you won't get the flashing xmas tree effect.
- TeMPOraL 6y agoI thought TFA meant flashing in the metaphorical sense - it's the code paths that light up, not things on the screen. Circular dependencies are an unfortunate fact of life, and I wish we had tools to deal with them, instead of desperately trying to avoid them. A good test for a UI paradigm is, how do you handle a UI like this: A = [50] [====| ] B = [10] [| ] C = [60] [=====| ] A + B = C Where [===| ] things are sliders, all three are changeable, and the relation A+B=C must always hold.
- amelius 6y agoYou can add a constraint solver on top of it. So when e.g. C changes, you solve for A and B. You then update the state of A, B, C and redraw. This kind of interaction can be handled by a separate library which is not necessarily part of a GUI system.
- auggierose 6y agoA constraint solver is overkill here, in particular as you cannot solve for A and B uniquely, you might want to add some further rule, like A and B should grow proportionally, when C is modified. But otherwise, yes, just use a framework that separates State from UI and has bidirectional updates, like SwiftUI.
- kilburn 6y agoThe problem is under-specified. When you move a slider, how should the other two adjust? There are many possible solutions and you haven't specified any preference here. The easiest solution is to maintain a fixed order of preference, something like: values = [a:0, b:0, c:0] fn onChange(key, value) { values[key] = value for (k,v) in values { if (k !== key) values[k] = adjust(k) } } fn adjust(key) { switch(key) { case 'a': return max(0, values[c] - values[b]) case 'b': return max(0, values[c] - values[a]) case 'c': return values[a] + values[b] } } The alternative is to maintain the latest selections made by the user and use that as the iteration order. Whatever approach you go with, the "single source of truth" approach of react/vue/svelte + state (whether it is state in hooks, redux, mobx or whatever) holds. The "values" above is the source of truth, and the components just reflect that. In other words: from a state point of view you don't have three sliders each with a value but a "three-valued component that happens to be shown as three sliders".
- diggan 6y agoReact itself doesn't have any way of "listening" to events, so the data is only flowing in one direction always. Redux et al introduces more things on top of that, where you can fire off events ("Actions" in Redux terms) that react/trigger other events, but doesn't really have anything to do with React itself. Then that some people make React components change state on render/mount/update, is a different failure, but not really a failure of React as much as a failure of the one using React. But in general no, React doesn't really prevent you from having a component updating and re-rendering because some state changed, and because of that, changes the state again and thus re-renders again, forever.
- jffhn 6y agoHad a similar issue while using a JTree, where programmatic nodes modifications generated events as if user had clicked on the tree, such as I had to override and disable a few JTree treatments to avoid triggering a wave of undesired side effects. That’s why in some framework I´m working on, the only events are those from input devices (keyboard, etc.) and windowing, views don’t generate any and are just here to paint the state and indicate to the controller where things are on the screen.
- MontagFTB 6y agoThis is a flaw in how the widgets have been implemented. When they serve as both the view and the controller, a common misarchitecture is to “loop back” a value change in the view back into the controller. This loop should _only_ happen as a result of the user interacting with the UI. To fix this, the controller does not modify its value authoritatively. Rather, it makes a request of the model to change the value it represents, then gets a confirmation or correction from the model once the logical state of the application has stabilized.