Prevent `segmented_control` forever loop edge case
Description
There's an extreme edge case where usage of segmented_control
could produce a forever loop. Let's figure out a nice way to prevent this from ever happening.
Context
The following discussion from !689 (merged) should be addressed:
-
@pslaughter started a discussion: (+3 comments) suggestion (non-blocking): I just realized that there's some cases where this
$emit('input')
onwatch('checked')
can cause a forever loop. Obviously we can't prevent the client of this component from doing something dangerous... If you think we can improve this, maybe it's worth a follow up issue🤷 While we're here what do you think of adding this bit where we don't submit a
oldValue
suggestion if it's equal to the new value (which can happen if they are objects/arrays). It's a bit paranoid I know....diff --git a/src/components/base/segmented_control/segmented_control.vue b/src/components/base/segmented_control/segmented_control.vue index 5906b8dd..0f8e63e2 100644 --- a/src/components/base/segmented_control/segmented_control.vue +++ b/src/components/base/segmented_control/segmented_control.vue @@ -47,8 +47,12 @@ export default { if (!this.enabledOptions.some(({ value }) => value === newValue)) { // eslint-disable-next-line no-console console.warn(genericErrorMessage); + + // prevent a forever loop when values are objects + const suggestion = oldValue && newValue !== oldValue ? oldValue : null; + if (this.enabledOptions.length) { - this.$emit('input', oldValue || this.enabledOptions[0].value); + this.$emit('input', suggestion || this.enabledOptions[0].value); } } },
/cc @xanf