ionic-framework icon indicating copy to clipboard operation
ionic-framework copied to clipboard

bug: React IonRange gets into infinite render loop

Open jamiechong opened this issue 4 years ago • 6 comments

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

jamiechong avatar Apr 22 '20 05:04 jamiechong

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 emits the ionChange event, which eventually calls setRange and causes the component to re-render, which updates the value prop of IonRange, which emits 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.

jamiechong avatar Apr 23 '20 05:04 jamiechong

Any updates on this issue? Using ionic/react 5.4.1 the issue is still present and don't have any workaround.

nicolascepeda avatar Oct 27 '20 10:10 nicolascepeda

This still seems to be an issue and it's quite a serious one. Are there any updates?

jamesopstad avatar Jul 06 '21 14:07 jamesopstad

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.

CameronCT avatar Dec 06 '21 07:12 CameronCT

Has no one fixed this problem ?

Sunnyjson avatar Jan 16 '22 15:01 Sunnyjson

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

sean-perkins avatar Jul 06 '22 18:07 sean-perkins

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.

sean-perkins avatar Nov 09 '22 20:11 sean-perkins

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.

ionitron-bot[bot] avatar Dec 09 '22 20:12 ionitron-bot[bot]