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

bug: `IonRange` does not render dual knobs correctly when value is set initially

Open sean-perkins opened this issue 1 year ago • 2 comments

Prerequisites

Ionic Framework Version

  • [ ] v4.x
  • [ ] v5.x
  • [X] v6.x
  • [ ] Nightly

Current Behavior

When IonRange initially renders with an initial value and dual knobs, the dual knobs will not display with their correct value position. This happens when either setting the value inline, against a variable reference or using useState.

If you cause a re-render of the component, the knobs will render correctly.

Expected Behavior

The dual knobs should render with the values assigned.

Steps to Reproduce

  1. Open reproduction URL
  2. Observe: Dual knobs are not displayed (both knobs are 0 position)
  3. Click "Cause Re-Render"
  4. Observe: The two range elements not bound to a state variable are rendered correctly

Code Reproduction URL

https://stackblitz.com/edit/angular-t1fufz?file=src%2Fmain.tsx

Ionic Info

N/A

Additional Information

No response

sean-perkins avatar Jun 09 '22 17:06 sean-perkins

Hi, loving the package so far.

Any update on this issue? Has anyone found a workaround?

I tried a hacky solution of manually emitting an event (in @ionic/react 6) using a ref, but no luck.

Thanks!

mepc36 avatar Aug 04 '22 17:08 mepc36

Since there's a special place in hell for devs who ask a question and then never post their answer (haha), here's mine:

Basically, add a button that you programmatically click post-render, and hide said button:


import React from 'react'
import { IonApp, IonContent, IonModal, IonRange, IonButton } from '@ionic/react'

export function MyComponent() {
  const [range, setRange] = useState({})
  const resetButtonRef = useRef()

  return (
    <IonApp>
      <IonContent>
        <IonModal
          onDidPresent={() => {
            resetButtonRef.current.click()
          }}
        >
          <IonRange
            pin
            ticks
            dualKnobs
            min={...}
            max={...}
            value={range}
            onIonChange={event => {
              setRange(event.detail.value)
            }}
          />
          <IonButton
            ref={resetButtonRef}
            style={{ display: 'none' }}
            onClick={() => {
              setRange(range)
            }}
          />
        </IonModal>
      </IonContent>
    </IonApp>
  )
}

mepc36 avatar Aug 08 '22 22:08 mepc36

I used a hack using useEffect hook and setTimeout function to set the values after the component is rendered. And it worked for me

import React,{ useEffect,useState } from 'react'
import { IonApp, IonContent, IonItem, IonRange, IonButton } from '@ionic/react'

export function MyComponent() {
  const [range, setRange] = useState({})

  useEffect(() => {
    setTimeout(() => {
      setRange({ lower: 10, upper: 20 }); // set default values as required
    }, 10)
  }, [])

  return (
    <IonApp>
      <IonContent>
        <IonItem>
          <IonRange
            pin
            ticks
            dualKnobs
            value={range}
            onIonChange={e => {
              setRange(e.detail.value)
            }}
          />
        </IonItem>
      </IonContent>
    </IonApp>
  )
}

4sagar avatar Jan 24 '23 05:01 4sagar

@mepc36 Please checkout my above solution if that works for you. Thank.

4sagar avatar Jan 24 '23 05:01 4sagar

I used a hack using useEffect hook and setTimeout function to set the values after the component is rendered. And it worked for me

import React,{ useEffect,useState } from 'react'
import { IonApp, IonContent, IonItem, IonRange, IonButton } from '@ionic/react'

export function MyComponent() {
  const [range, setRange] = useState({})

  useEffect(() => {
    setTimeout(() => {
      setRange({ lower: 10, upper: 20 }); // set default values as required
    }, 10)
  }, [])

  return (
    <IonApp>
      <IonContent>
        <IonItem>
          <IonRange
            pin
            ticks
            dualKnobs
            value={range}
            onIonChange={e => {
              setRange(e.detail.value)
            }}
          />
        </IonItem>
      </IonContent>
    </IonApp>
  )
}

Nice! i try this.

teomda avatar Aug 15 '23 14:08 teomda

It seems like a very dirty hack and the default value should be displayed correctly without it. Are there any updates on this bug?

KuschL avatar Sep 26 '23 09:09 KuschL

Hello everyone 👋

Here is a dev-build to validate with: 7.4.3-dev.11695926109.13b1266a

Forked reproduction: https://stackblitz.com/edit/angular-t1fufz-rd74ue?file=package.json

Let me know if you experience any issues.

sean-perkins avatar Sep 28 '23 19:09 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 Oct 28 '23 20:10 ionitron-bot[bot]