Sharcoux / slider

React-Native and React-Native-Web compatible slider
ISC License
161 stars 31 forks source link

Prevent thumb beyond min/max values #103

Open jbaxleyiii opened 1 week ago

jbaxleyiii commented 1 week ago

I'm not sure this is a bug or (more likely!) me misunderstanding the min/max props. I'd like to be able to create a slider for a date range (i.e. it starts at 0 and ends at 24) but only make a certain window inside that selectable. I tried doing this:

<RangeSlider
    range={[0, 24]}
    minimumValue={7}
    maximumValue={21}
    step={0.5}
/>

but I was still able to select less than 7 and greater than 21 on the slider. Is there a way to set only a portion of the overall range to be selectable?

Sharcoux commented 1 week ago

I'll see how you ended up being able to pass values below the min and above the max. That should not be possible. However, for your problem, you just need to use onValueChange to force the value

const [range, setRange] = React.useState([7, 21])

return <Slider
  range={range}
  minimumValue={0}
  maximumValue={24}
  onValueChange={newRange => setRange(newRange.map(val => Math.min(Math.max(val, 7), 21)))}
/>
Sharcoux commented 1 week ago

I could not reproduce the problem of having the slider go beyond the min and max values. You'll have to provide a minimal reproducible example, ideally in snack expo.

jbaxleyiii commented 1 week ago

@Sharcoux you bet! https://snack.expo.dev/@jamesbaxleyiii/slider-min-max

You can see that doing it with onValuechange still allows the thumb to be moved past a min or max value.

Sharcoux commented 3 days ago

Indeed, that's an annoying problem. The value prop is being used as an initial value. When it changes, we update the value of the inner state accordingly. However, there is currently no way to prevent the value from being updated because, if we set the value to what it was before, that won't trigger a rerender as the prop didn't change. I'll see if I find a solution.

Sharcoux commented 3 days ago

I see 2 options. One is to decide if we are using a controlled value or not based on what we receive as "value" prop. The issue is that this will make it more complex and less intuitive to provide an initial value. Another option is to make the user able to cancel updates during onValueChange or onSlidingComplete. We could either consider that returning false should cancel the update, or pass a "cancel" callback, or add a new prop named "onBeforeValueChange" for instance.

I think that I should go with that second option but I'd like to have feedbacks on that.

jbaxleyiii commented 2 days ago

I think a new prop is probably a good way to keep it non-breaking and more of an advanced option!