You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The simplest example that demonstrates this pattern is:
<divid="app"><h2>controll text field can lead to inconsistent state</h2><inputtype="text" :value="name" @input="handleInput"/>
force update:
<inputtype="checkbox" v-model="forceUpdateWorkaround"/></div>
When typing 'b' in the text field, it shows 'FOOB' in all caps, which mirrors the value data. However, when we replace the last B' with a 'b', the text field will change to 'FOOb', but the event handler (handleInput`) will not change the vue model, and therefore not update the component. Now, the internal data model and the DOM are inconsistent
Discussion
This is a rare and subtle (and therefore, I think dangerous) bug that can result from this pattern. ReactJS does not have this problem (see above example). What I think ReactJS does is that it will update the DOM with the vDOM for the DOM element that triggered the event. I think this makes a lot of sense since DOM element events can be the source of internal state changes (like the value of a text field), but those events do not always trigger re-renders in the frameworks (since state changes may not happen, as demonstrates above). In this edge case, a state change in a DOM element without an associated state change in the VueJS framework can cause inconsistencies.
Some background
We hit the same issues in a Python framework called Solara which is similar to React, and we were comparing how other frameworks solve this problem. We found that SolidJS and VueJS have this issue, while ReactJS does not. In the end, we use a solution similar to ReactJS in our underlying framework: widgetti/reacton#45
Proposed solution
VueJS should always update the DOM element that triggered an event if, after handling its event handlers, it did not trigger a rerender.
The text was updated successfully, but these errors were encountered:
That is a common 'workaround', but it will trigger a change with an invalid value. For instance, in the above example, it will trigger both 'FOOb' and 'FOOB'. I don't think if you do proper state management that is acceptable.
But more importantly, using the pattern of value + onChange usually work. So if you use this pattern throughout your app, you might feel confident your app is without bugs, and then in this really strange edge case, your app is in an inconsistent state.
Context
In React it's very common to have a controlled component. e.g. like this https://codesandbox.io/p/devbox/react-dev-forked-85xg4s where the state completely lives outside of the child component.
Although I don't think in the VueJS ecosystem uses the same wording, I have seen this pattern being used (e.g. https://stackoverflow.com/questions/68496743/vue-js-input-value-not-reflecting-value-in-component-data/79472786 which also demonstrates the issue I'm about to describe).
More indirect versions of this are where an event gets forwarded to a Vuex store, and the component (should) show the resulting state from the store.
Demonstration of bug
The simplest example that demonstrates this pattern is:
(full example here
When typing 'b' in the text field, it shows 'FOOB' in all caps, which mirrors the
value
data. However, when we replace the lastB' with a 'b', the text field will change to 'FOOb', but the event handler (
handleInput`) will not change the vue model, and therefore not update the component. Now, the internal data model and the DOM are inconsistentDiscussion
This is a rare and subtle (and therefore, I think dangerous) bug that can result from this pattern. ReactJS does not have this problem (see above example). What I think ReactJS does is that it will update the DOM with the vDOM for the DOM element that triggered the event. I think this makes a lot of sense since DOM element events can be the source of internal state changes (like the value of a text field), but those events do not always trigger re-renders in the frameworks (since state changes may not happen, as demonstrates above). In this edge case, a state change in a DOM element without an associated state change in the VueJS framework can cause inconsistencies.
Some background
We hit the same issues in a Python framework called Solara which is similar to React, and we were comparing how other frameworks solve this problem. We found that SolidJS and VueJS have this issue, while ReactJS does not. In the end, we use a solution similar to ReactJS in our underlying framework: widgetti/reacton#45
Proposed solution
VueJS should always update the DOM element that triggered an event if, after handling its event handlers, it did not trigger a rerender.
The text was updated successfully, but these errors were encountered: