React Native TouchableOpacity does not update styles

I have a strange problem with the TouchableOpacity component. I have a MainButton component that accepts 2 MainButton , item and disabled . Based on disabled prop, I want my MainButton component to use a different style. The problem is that the TouchableOpacity re reenders component does not update the style. The prop disabled icon is correctly set to re render.

What makes it strange is that if I change it to TouchableHeighlight , it will work as expected.

Does anyone know why? Is this a bug in TouchableOpacity?

 import React, { Component } from 'react' import UI from '../styles/ui' import { Text, TouchableOpacity } from 'react-native' const ui = new UI() const styles = ui.styles class MainButton extends Component { constructor (props) { super(props) this.state = { disabled : props.disabled, item: props.item } } componentWillReceiveProps(props) { this.setState({disabled:props.disabled}) } render() { var normalStyles = [styles.mainButton,styles.widthEighty] var disabledStyle = [styles.mainButton,styles.widthEighty,styles.lowOpacity] var correctStyles = this.state.disabled ? disabledStyle : normalStyles console.log(this.state.disabled,'this.state.disabled ? '); return ( <TouchableOpacity disabled={this.state.disabled} style={correctStyles} accessibilityLabel={this.state.item.name} onPress={this.state.item.onPress.bind(this)}> <Text style={styles.mediumLabel}>{this.state.item.name}</Text> </TouchableOpacity> ); } } export { MainButton as default } 
+9
source share
3 answers

I don’t have enough context to understand what exactly you are trying to achieve, but try the following:

  <TouchableOpacity disabled={this.state.disabled} style={this.state.disabled ? disabledStyle : normalStyles} accessibilityLabel={this.state.item.name} onPress={this.state.item.onPress.bind(this)}> <Text style={styles.mediumLabel}>{this.state.item.name}</Text> </TouchableOpacity> 

Also, there is not enough context about what this.state.item.onPress does, or why you use the element that you pass into the props, in order to replace the props in the first place. It looks like you can improve the way you implemented this, if you give me more context, I could help.

0
source

Firstly, I don’t think that I will pass the disabled and item details. You can do this directly and get rid of the constructor, as well as componentWillReceiveProps . componentWillReceiveProps lifecycle method will become obsolete soon, so it does not encourage its use.

Also, if possible, separate the event handler from the item details. This is not the best way to do this.

 render () { const { disabled, item, onPress } = this.props; const { name } = item; ... return ( ... <TouchableOpacity disabled={disabled} style={disabled ? disabledStyle : normalStyle} accessibilityLabel={name} onPress={onPress} > <Text style={styles.mediumLabel}>{name}</Text> </TouchableOpacity> ... ); } 
0
source

The workaround I came up with is to use

setOpacityTo(value) for updating the canvas.

I did this componentDidUpdate() since this lifecycle method is called whenever your new style is applied to your component. So I gave the <TouchableOpacity/> ref component and updated it whenever its style changed.

Example:

 import React, { Component } from 'react' import UI from '../styles/ui' import { Text, TouchableOpacity } from 'react-native' const ui = new UI() const styles = ui.styles class MainButton extends Component { constructor (props) { super(props) this.state = { disabled : props.disabled, item: props.item } } componentWillReceiveProps(props) { this.setState({disabled:props.disabled}) } componentDidUpdate() { this.refs['touchable'].setOpacityTo(1.0); } render() { var normalStyles = [styles.mainButton,styles.widthEighty] var disabledStyle = [styles.mainButton,styles.widthEighty,styles.lowOpacity] var correctStyles = this.state.disabled ? disabledStyle : normalStyles console.log(this.state.disabled,'this.state.disabled ? '); return ( <TouchableOpacity ref={'touchable'} disabled={this.state.disabled} style={correctStyles} accessibilityLabel={this.state.item.name} onPress={this.state.item.onPress.bind(this)}> <Text style={styles.mediumLabel}>{this.state.item.name}</Text> </TouchableOpacity> ); } } export { MainButton as default } 
0
source

Source: https://habr.com/ru/post/1271297/


All Articles