Непрозрачность компонента React Native не обновляется при обновлении реквизита

У меня есть дочерний компонент React Native, который отображает кнопку в полупрозрачном состоянии, если для свойства disabled установлено значение true. Свойство, вероятно, будет обновлено после первоначальной загрузки приложения (после того, как оно получит свои данные), поэтому это не будет начальным состоянием компонента.

Я вижу, что когда я взаимодействую с кнопкой, она меняет свое состояние, но почему-то не раньше. Как по логам, так и по поведению onPress я вижу, что свойство обновляется. Я пробовал разные подходы, но ни один из них не решил проблему.

class TestButton extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
    const buttonOpacity = (this.props.disabled  ? disabledOpacity : 1.0);
    console.log ("test disabled", this.props.disabled, buttonOpacity);

    return (
      <BubbleText style={{opacity: buttonOpacity}} onPress={
        () => ! this.props.disabled && doSomething() }>
          { this.props.testNumber }
      </BubbleText>
    );
  }
}

person Adamski    schedule 15.01.2018    source источник
comment
Трудно сказать, в чем дело. Что делает loadTest?   -  person azium    schedule 16.01.2018
comment
он загружает тест.. Я удалю его для ясности   -  person Adamski    schedule 16.01.2018
comment
Можешь перефразировать свой вопрос? Я прочитал это раз 5, и я до сих пор не понимаю, что происходит и что ожидается.   -  person azium    schedule 16.01.2018
comment
В предоставленном вами коде не происходит ничего странного, поэтому происходит что-то еще странное (если вообще происходит что-то странное)   -  person azium    schedule 16.01.2018
comment
@azium обновлен, спасибо   -  person Adamski    schedule 16.01.2018


Ответы (5)


Кажется, есть проблема с настройкой непрозрачности кнопок TouchableOpacity. Я использую [email protected]. Если непрозрачность установлена, а затем обновлена, новая визуализация не меняет значение непрозрачности, даже если оно передается в стиль компонента.

Есть собственный способ сделать это с помощью TouchableOpacity. Это также выигрывает от отключения всех событий прессы при использовании реквизита disabled.

<TouchableOpacity
    disabled={ this.props.is_disabled }
    activeOpacity={ this.props.is_disabled ? .6 : 1 }>
    <Text>Custom Button</Text>
</TouchableOpacity>

Одно предостережение к вышеизложенному: установка activeOpacity не меняет непрозрачность текста, а только backgroundColor.

В качестве альтернативы использование значений rgba для указания непрозрачности действительно работает.

export class CustomButton extends Component {

    get_button_style() {
        let _button_style = [this.props.button_style]

        if (this.props.is_disabled) {
            _button_style.push({
                backgroundColor: 'rgba(0, 0, 0, .6')
            });
        }

        return _button_style;
    }

    render() {
        return(
            <TouchableOpacity
                style= { this.get_button_style() }>
                <Text> Custom Button </Text>
            </TouchableOpacity>
        )
    }
}
person kgstew    schedule 03.07.2018
comment
Другой вариант — обернуть TouchableOpacity в представление. Затем вместо этого установите непрозрачность в представлении. - person rolznz; 22.02.2019

Похоже на известную проблему https://github.com/facebook/react-native/issues/17105

Одним из обходных путей является перенос содержимого вашего TouchableOpacity в представление и применение стиля непрозрачности к этому представлению, а не непосредственно к непрозрачности Touchable.

person Pnar Sbi Wer    schedule 11.09.2018
comment
Ничего себе, используя RN 0.60.4 в настоящее время, и эта ошибка все еще возникает. Этот обходной путь работает, но кажется грязным! Благодарю. - person msqar; 06.08.2019

Только по фрагменту сложно сказать, возможно, проблема в родительском компоненте, использующем этот. Добавление кода для этого может помочь определить, в чем проблема.

Извините, недостаточно представителей, чтобы добавить комментарий.

person Nemi Shah    schedule 16.01.2018
comment
Добавлен родительский компонент. - person Adamski; 17.01.2018
comment
Пробовали ли вы использовать componentWillRecieveProps, чтобы проверить, правильно ли тестовая кнопка получает обновленные реквизиты? - person Nemi Shah; 18.01.2018
comment
Да, я так думаю, как я уже сказал, я также могу видеть через операторы журнала и другие аспекты пользовательского интерфейса, например. onPress поведение. - person Adamski; 18.01.2018

Базовым компонентом был TouchableOpacity. Кажется, есть проблема с настройкой его непрозрачности извне. В этом случае я решил проблему, явно определив цвета, не используя непрозрачность:

class TestButton extends React.Component {

  constructor(props) {
    super(props);
  }

  render() {
      return (
        <BubbleText fill={this.props.disabled ? disabledFill : undefined} textStyle={this.props.disabled ? {color: disabledText} : {}} onPress={
          () => ! this.props.disabled && loadTest(this.props.navigator, this.props.set + this.props.testNumber, this.props.children)
          }>
            { this.props.testNumber }
          </BubbleText>
          );

  }
}

В другой части моего кода я добавил условие для отображения компонента как View с непрозрачностью, если он отключен, и TouchableOpacity, если нет.

person Adamski    schedule 18.01.2018
comment
Не знал, что это может вызвать проблему. Хорошо знать. Рад, что вы решили это - person Nemi Shah; 18.01.2018

Используйте TouchableOpacity из обработчика react-native-gesture-handler, у него есть поддержка с именем containerStyle, ваш TouchableOpacity автоматически обновит непрозрачность, когда this.props.is_disabled будет ложным или истинным. Без этого вам нужно будет перезапустить приложение, чтобы показать непрозрачность:

<TouchableOpacity onPress={() => {}} 
                    disabled={this.props.is_disabled} 
                    containerStyle={{
                        opacity: this.props.is_disabled ? 1 : .4,
                    }}
                    style={}>
                </TouchableOpacity>
person Otavio    schedule 16.08.2020