当组件在本机反应中重新呈现时,动态不透明度不会改变

Posted

技术标签:

【中文标题】当组件在本机反应中重新呈现时,动态不透明度不会改变【英文标题】:Dynamic Opacity not changing when component rerenders in react native 【发布时间】:2018-06-07 08:55:24 【问题描述】:

我开始学习 React Native,并为我的项目创建了一个简单的 Button 组件以在我的项目中重用。我根据变量“禁用”动态设置不透明度值,但是,按钮的外观不会随着不透明度变量的值而改变。我四处寻找,我没有找到解释.. 任何帮助将不胜感激。

这是我的源代码:

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>
            )
    

如果 newDeck 组件的标题为空或 null,则 disabled 变量为 true。当这个变量为真时,按钮的不透明度应该只有 0.5。当该值变为 false 时,不透明度再次变为 1。如果我记录组件中的不透明度值,我可以看到它从 0.5 变为 1,但组件的外观没有改变。

【问题讨论】:

代码中的任何内容都无法控制动态呈现。你想做什么? 只是一个按钮,如果禁用变量为真,则不透明度会发生变化。 让我们看看你是如何使用那个按钮的 @FacundoLaRocca 我提供了更多信息! 你能把不透明度放在TouchableOpacity文本里面,看看它是否改变 【参考方案1】:

对我来说,当我还更改了 disabled 属性和不透明度时,它就起作用了。

我猜问题是TouchableOpacity 中的不透明度是一个Animated.Value,它会覆盖style 道具中的值并且不会改变,当style 道具发生变化时...

【讨论】:

【参考方案2】:

如果您使用的是 React Native 0.63 版 及更高版本,那么 Pressable 是更优雅的解决方案,它的不透明度更改按预期工作。

<Pressable
    style=
       opacity: item.isSelected ? 0.5 : 1
    >
       //Your button content goes here
</Pressable>

【讨论】:

【参考方案3】:

我认为正确的解决方案是使用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>
  );

接下来你可以在componentDidUpdate 中使用setOpacityTo 方法对disabled 的道具进行更改:

  componentDidUpdate(prevProps) 
    const  disabled  = this.props;
    if (disabled !== prevProps.disabled) 
      const opacityValue = disabled ? 0.5 : 1;
      this.btn.setOpacityTo(opacityValue);
    
  

【讨论】:

【参考方案4】:

不确定是否是 TouchableOpacity 组件上的错误,但在单击组件之前,不透明度不会在重新渲染时更新

要解决您的问题,只需将可触摸的内容包装在 View 中,然后将 opacity 应用于视图而不是可触摸

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>
    )


【讨论】:

很高兴,如果对您有用,请确保将答案标记为正确。 你救了我的命。谢谢 在不点击组件的情况下更新不透明度已与您的解决方法一起使用,但仍然不透明度已延迟更新。有什么办法解决吗? 不要只对可触摸的视图应用不透明度

以上是关于当组件在本机反应中重新呈现时,动态不透明度不会改变的主要内容,如果未能解决你的问题,请参考以下文章

更新 Redux 存储时反应组件不重新渲染

当状态改变时,对文本字段做出反应 onChange 更新整个组件

当状态改变时,React不会重新渲染我的组件

嵌套反应路由器组件不会在页面重新加载时加载/渲染?

反应父组件不重新渲染

等待反应上下文后组件不重新渲染