alantoa / react-native-awesome-slider

🚀 An anwesome <Slider/> that supports various features haptic, lottie, animation, ballon, etc.
MIT License
228 stars 28 forks source link

How to set initial step? #47

Closed wilmxre closed 8 months ago

wilmxre commented 8 months ago

I would like to have the slider at a given starting step, when you see the slider intially. So let's say i have a slider with 4 steps, when the slider is in view for the first time, on initial render, i would like it to be at step 2. Now every time the slider in rendered, it starts at 0.

I thought the progress prop is responsible for this, but it always stays at 0. Even if i set arbitrary numbers to it.

This is how my values are defined:

 const progress = useSharedValue(volumeLevel);
 const min = useSharedValue(1);
 const max = useSharedValue(5);

and the Slider component:

        <Slider
          step={4}
          progress={progress}
          minimumValue={min}
          maximumValue={max}
          sliderHeight={4}
          thumbWidth={18}
          bubbleMaxWidth={58}
          renderMark={renderMark}
          renderBubble={renderBubble}
          onSlidingComplete={onSlidingComplete}
          onValueChange={onValueChange}
          style={styles.slider}
          theme={theme}
        />

How should i set an initial step position where the slider will be?

I looked into the source code and i managed to do this by passing a value to const thumbIndex = useSharedValue(0);, instead of 0, but this way the slider is at 0 for a few milliseconds, then it snaps to the desired step. And this can be frustrating to the user.

What am i doing wrong?

efstathiosntonas commented 8 months ago

How volumeLevel is fed to useSharedValue? Is it coming from state? What happens if you hard code this value?

wilmxre commented 8 months ago

yes, it is coming from a state passed from its father component. i tried hardcoding 1 or 2, but the slider stays at step 0 if i console log the progress.value i get the value of the actual volumeLevel in #46 i just saw that if you don't specify the step prop, it works like intended, so i tried it out and it works that way

wilmxre commented 8 months ago

i don't really know how the slider was implemented, but i noticed that if i pass the progress.value directly to const thumbIndex = useSharedValue(progress.value - 1); (in my case progress.value -1, because i am starting from 1 instead of 0) it works how it is supposed to

also i am using:

"react-native-reanimated": "~3.3.0",
"react-native-gesture-handler": "~2.12.0",

if this issue is related to the version of reanimated at all

wilmxre commented 8 months ago

i also realized that if the progress is fed from a state, it doesn't jump to the respective step at all. so let's say the parent component can control the value of progress from outside, the useSharedValue of the progress variable will not update the slider component at all, because it will always stay at the initial value of the state passed from the parent

efstathiosntonas commented 8 months ago

check useDerivedValue https://docs.swmansion.com/react-native-reanimated/docs/2.x/api/hooks/useDerivedValue/

something like this:

 const progress = useSharedValue(volumeLevel);

  const derived = useDerivedValue(() => {
    return progress
  }, [volumeLabel]);

<Slider
          step={4}
          progress={derived}
wilmxre commented 8 months ago

i tried it out with:

const progress = useSharedValue(volumeLevel);

const derived = useDerivedValue(() => {
    'worklet';
    return progress.value;
  }, [volumeLevel]);

  <Slider
          step={4}
          progress={derived}

but the value still stays at the initially passed one. these are my logs when the volumeLevel changes:

 DEBUG   [ANDROID] VolumeLevel:  1
 LOG   [ANDROID] Progress:  1
 INFO   [ANDROID] Derived:  1

 DEBUG   [ANDROID] VolumeLevel:  3
 LOG   [ANDROID] Progress:  1
 INFO   [ANDROID] Derived:  1

 DEBUG   [ANDROID] VolumeLevel:  4
 LOG   [ANDROID] Progress:  1
 INFO   [ANDROID] Derived:  1
computerjazz commented 8 months ago

I think the issue is that thumbIndex is only updated within the gesture callback, but it is used to set the slider index.

I changed this line: https://github.com/alantoa/react-native-awesome-slider/blob/a7a68d8a0cd05b11090dfbffc3400e29b6418ee2/src/slide.tsx#L266

to:

  const thumbIndex = useSharedValue(snapToStep && step ? progress.value - 1 : 0);

and it started working as expected. Not sure if this fix is correct in every case (ie do we want to set the thumbIndex whenever progress value changes?)

alantoa commented 8 months ago

Thanks for all of your feedback! I have just merged @computerjazz's PR and did a tiny improment, and i have also released a new version here!