ionic-framework
ionic-framework copied to clipboard
bug: React IonRange gets into infinite render loop
Bug Report
Ionic version:
[x] 5.0.7
Current behavior:
I'm using the IonRange
component with dualKnobs
. When trying to set a default value and update state with onIonChange
the parent component gets into an infinite render loop as soon as I update the range state.
Expected behavior:
I should be able set the default value of the lower
and upper
knobs by setting the value
prop of IonRange
. This works, but as soon slide one of the knobs, the parent component repeatedly re-renders forever.
Steps to reproduce:
Create a component with that renders an IonRange
component and also useState
. You can see an example here: https://stackblitz.com/edit/ionic-react-demo-tt4ytk?file=pages%2FHome.jsx
As soon as you adjust one of the knobs (and onIonChange
is called), you will see that the component is rendered in a loop - console.log('render')
is called repeatedly forever.
Related code:
const MyComponent = () => {
const defaultValue = {lower: 40, upper: 70};
const [range, setRange] = useState(defaultValue);
console.log('render');
return (
<IonRange dualKnobs={true} min={0} max={100} value={{...defaultValue}} onIonChange={ e => setRange(e.detail.value) }>
<IonLabel slot="start">{range.lower}</IonLabel>
<IonLabel slot="end">{range.upper}</IonLabel>
</IonRange>
);
};
Other information:
Ionic info:
Ionic:
Ionic CLI : 6.6.0
Ionic Framework : @ionic/react 5.0.7
Capacitor:
Capacitor CLI : 2.0.0
@capacitor/core : 2.0.0
Utility:
cordova-res : not installed
native-run : not installed
System:
NodeJS : v12.16.1
npm : 6.13.4
OS : macOS Catalina
I believe the problem is here in range.tsx
/**
* the value of the range.
*/
@Prop({ mutable: true }) value: RangeValue = 0;
@Watch('value')
protected valueChanged(value: RangeValue) {
if (!this.noUpdate) {
this.updateRatio();
}
value = this.ensureValueInBounds(value);
this.ionChange.emit({ value });
}
When React renders the IonRange
component, it sets the value from the range
state, which it's managing on its own. Inside IonRange
the new value emit
s the ionChange
event, which eventually calls setRange
and causes the component to re-render, which updates the value
prop of IonRange
, which emit
s the ionChange
event again, which triggers the setRange
call......
Now that I understand the issue, I've worked around this by only calling setRange
if the values have changed. It seems to break the loop. It might be worth considering a similar check before calling this.ionChange.emit({ value });
if the value, in fact, has not changed.
Any updates on this issue? Using ionic/react 5.4.1 the issue is still present and don't have any workaround.
This still seems to be an issue and it's quite a serious one. Are there any updates?
Odd that this hasn't been fixed over a year later. The current work around is putting return false
if the value matches your local state variable under onIonChange
.
Has no one fixed this problem ?
Hello everyone, we have an open RFC that proposes a change to ionChange
that would help alleviate this issue.
Please take a moment to review and let us know your thoughts: https://github.com/ionic-team/ionic-framework/discussions/25532
Hello everyone, this issue is resolved as of: https://github.com/ionic-team/ionic-framework/pull/26089 and will be available in the next major release (v7) of Ionic.
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.