This is a question for someone who understands React/RN better than I. When I wrap touchable components (i.e. buttons) in a lightweight wrapper with a debounce function (to prevent onPress handler from being called too rapidly), it usually works as intended. HOWEVER, in a very specific set of circumstances, things go awry. If I pass a parent component's state down into the onPress prop of the button, if the state property I'm accessing has been destructured in the render method and then passed as this variable, rather than simply accessed as this.state.foo, the onPress handler reads it as its initial state value, even if it has been updated. This is probably confusing so allow me to show you a quick, incomplete example:
class DebounceButton extends Component {
handlePress = debounce(this.props.onPress, 500)
render() {
return (
<Button onPress={this.handlePress}
)
}
}
class Screen extends Component {
state = {
foo: 0
}
render() {
const { foo } = this.state
return (
<Button onPress={() => {this.setState({ foo: this.state.foo + 1 })}}/>
<DebounceButton onPress={() => {console.log(foo)}}/>
<DebounceButton onPress={() => {console.log(this.state.foo)}}/>
)
}
}
If I press Button, foo increments to 1. If I then press the first DebounceButton, the console will log 0. If I press the second, it will log 1 as it should. Note it only happens when state is passed through the debounce function AND assigned to a variable in the render method. It's as if React is "forgetting" what the current state is and default to its initial value. This is no longer a bug for me as I'm not using this debounce paradigm anymore, but I'm curious to understand it to better so I can have a better grasp on the way React works. Any insight is greatly appreciated.
The class property handlePress = debounce(this.props.onPress, 500) will only be evaluated when DebounceButton is first created, so changing the onPress after it has first been rendered does not work.
You could instead create a new function that invokes this.props.onPress inside of it. This way the current value of this.props.onPress will be used every time.
class DebounceButton extends Component {
handlePress = debounce(() => {
this.props.onPress();
}, 500);
render() {
return <Button onPress={this.handlePress} />;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With