Динамическая непрозрачность не изменяется, когда компонент перерисовывается в реагирующем нативе
Я начинаю изучать React Native, и для своего проекта я создал простой компонент Button для повторного использования в моем проекте. Я устанавливаю значение непрозрачности динамически в соответствии с переменной "disabled", однако внешний вид кнопки не меняется со значением переменной opacity. Я искал вокруг, и я не нашел объяснения..
Любая помощь будет оценена.
Вот мой исходный код:
import React from 'react'
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'
import PropTypes from 'prop-types'
//TODO: arrumar o problema com a opacidade
export default function Button({text, onPress, style, disabled, textStyle}) {
let opacity = disabled === true ? 0.5 : 1
// console.log('opacity', opacity)
return (
<TouchableOpacity onPress={onPress} style={[defaultStyles.button, style, {opacity: opacity}]}
disabled={disabled}>
<Text style={[defaultStyles.text, textStyle]}>{text}</Text>
</TouchableOpacity>
)
}
const defaultStyles = StyleSheet.create({
text: {
color: 'white'
},
button: {
backgroundColor: 'black',
margin: 15,
padding: 15,
borderRadius: 10
},
})
Button.propTypes = {
text: PropTypes.string,
onPress: PropTypes.func,
style: PropTypes.oneOfType([
PropTypes.string,
PropTypes.array,
PropTypes.object
]),
disabled: PropTypes.bool,
textStyle: PropTypes.oneOfType([
PropTypes.string,
PropTypes.array,
PropTypes.object
])
}
РЕДАКТИРОВАТЬ: Вот код, который вызывает кнопка
class NewDeck extends Component {
state={
title: null
}
submit = () => {
const { add, goBack } = this.props
let deck = {...this.state}
if(!deck['deckId']){
deck['deckId'] = Date.now()
deck['logs'] = []
}
!deck['cardsId'] && (deck['cardsId'] = [])
add(deck).then(() => {
this.props.navigation.navigate('Deck', {deckId: deck.deckId, title: deck.title})
this.setState({title: null})
}
)
}
render(){
const disabled = this.state.title === null || this.state.title.length === 0
return (
<KeyboardAwareScrollView resetScrollToCoords={{ x: 0, y: 0 }}
contentContainerStyle={styles.container}>
<Text style={textStyles.title2}>Whats the title of your deck?</Text>
<TextInput editable={true} style={[styles.input, textStyles.body]}
placeholder='Type title here'
maxLength={25}
value={this.state.title}
onChangeText={(text) => {
this.setState({title: text})
}}
/>
<Button
onPress={this.submit}
text='Submit'
style={{backgroundColor: colors.pink}}
textStyle={textStyles.body}
disabled={!this.state.title}
/>
</KeyboardAwareScrollView>
)
}
}
Отключенная переменная имеет значение true, если заголовок компонента newDeck пуст или равен нулю. Когда эта переменная имеет значение true, непрозрачность кнопки должна быть только 0,5. Когда значение становится ложным, непрозрачность снова меняется на 1. Если я записываю значение непрозрачности в компонент, я вижу, что оно изменяется от 0,5 до 1, но внешний вид компонента не меняется.
5 ответов
Не уверен, что это ошибка в компоненте TouchableOpacity, но непрозрачность не будет обновляться при повторном рендеринге, пока компонент не будет нажат
чтобы решить вашу проблему, просто оберните содержимое сенсорного в представлении и примените непрозрачность к представлению вместо сенсорного
export default function Button({text, onPress, style, disabled, textStyle}) {
const opacity = disabled === true ? 0.5 : 1
// console.log('opacity', opacity)
return (
<TouchableOpacity onPress={onPress} disabled={disabled}
style={[defaultStyles.button, style]}>
<View style={{opacity}}>
<Text style={[defaultStyles.text, textStyle]}>{text}</Text>
</View>
</TouchableOpacity>
)
}
Для меня это сработало, когда я также изменил
disabled
prop вместе с непрозрачностью.
Я предполагаю, что проблема в том, что непрозрачность в
TouchableOpacity
является
Animated.Value
который переопределяет значение в реквизите и не изменяется, когда
style
реквизит меняется...
На мой взгляд, правильным решением является использование метода setOpacityTo.
В вашем render
:
render() {
const opacityValue = this.props.disabled ? 0.5 : 1;
return (
<TouchableOpacity style={{ opacity: opacityValue }} ref={(btn) => { this.btn = btn; }} onPress={this.onPress}>
<Text>{this.props.text}</Text>
</TouchableOpacity>
);
}
И рядом вы можете использовать setOpacityTo
метод в componentDidUpdate
на disabled
изменение реквизита:
componentDidUpdate(prevProps) {
const { disabled } = this.props;
if (disabled !== prevProps.disabled) {
const opacityValue = disabled ? 0.5 : 1;
this.btn.setOpacityTo(opacityValue);
}
}
Если вы используете React Native версии 0.63 и новее, Pressable - более элегантное решение, и его изменение непрозрачности работает должным образом.
<Pressable
style={{
opacity: item.isSelected ? 0.5 : 1
}}>
//Your button content goes here
</Pressable>
У меня та же проблема, это странное поведение, просто добавьте компонент View с желаемым стилем внутри компонента TouchableOpacity следующим образом:
<TouchableOpacity >
{/* this view is just because opacity doesn't work dynamically on touchable opacity */}
<View style={{opacity : (loading)? 0.5 : 1 }}>
<Text>Your text here</Text>
</View>
</TouchableOpacity>