msqar
msqar

Reputation: 3040

React Native Slider - onValueChange invoked too many times

I'm creating a Slider on my app but whenever I start dragging the thumb, it keeps flickering. It's because I'm using the state directly and storing it whenever it changes. I'd like for the value to update whenever I move it not only when I stopped. Tried using a common variable out of the state with forceUpdate() but it happens the same thing, multiple updates lag a lot.

This is the code I'm using to create the slider

export default class Profile extends Component {

constructor(props) {
   super(props)
   this.state = { age: 18 }
  } 

  render() {    

    return (
      <View style={styles.container}>
        <Slider
         style={{ width: 300 }}
         step={1}
         minimumValue={18}
         maximumValue={71}
         value={this.state.age}
         onValueChange={val => this.setState({ age: val })}
        />
        <Text style={styles.welcome}>
          {this.state.age}
        </Text>            
      </View>
    );
  }
}

In order to stop the flickering I'm using the onSlidingComplete parameter to update the state, but that only triggers when I release the finger from the component. Not the desired effect.

Should I add a debounce or something on this setState?

Upvotes: 2

Views: 2667

Answers (2)

Filip Savic
Filip Savic

Reputation: 3238

You can stop the lag by commenting out the value prop of the <Slider />. That prop is just for the initial slider value, but it is creating the lag...

I am assuming you want to display the slider value in a <Text> component somewhere. You can do that by creating 2 pieces of state for the actual, logical piece of state that you have. One of those 2 would display the data in a text component (and you would update it onValueChange) while the other one would update the actual slider value and could be used as the 'value' prop (and you would update it onSlidingComplete).

I wrote a detailed answer (with code) here.

Upvotes: 3

VulfCompressor
VulfCompressor

Reputation: 1410

You can either debounce or throttle the setState call. With Lodash:

....
onValueChange={_.debounce(this.setAge, 33)} // 30 updates per second
onValueChange={_.debounce(this.setAge, 16)} // 60 updates per second (too much!)
....

setAge(age) {
    // Don't forget to bind this function to your component on the Constructor function!
    this.setState({ age })
}

Upvotes: 3

Related Questions