React Native (с Redux) анимирует Switch программно

У меня есть компонент, который имеет компонент Switch внутри. Весь этот компонент кликабелен. Когда вы щелкаете по этому компоненту, он запускает диспетчеризацию (которая изменяет избыточное хранилище) и вызывает повторную визуализацию этого компонента. Мне нужно не перерисовать весь компонент, а просто анимировать этот компонент Switch в правильное состояние.

Что-то вроде этого

<TouchableOpacity onPress={onPress}>
    <Text>{this.props.title}</Text>
    <Switch value={this.state.active}/>
</TouchableOpacity>

Любая идея?

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

Спасибо

--- РЕДАКТИРОВАТЬ ---

Я тоже попробовал это. Я пытался отключить обновление с помощью shouldComponentUpdate, я пытался установить состояние только в willRecieveProps и / или переключении, даже без переключения. Я также пытался играть с LayoutAnimation. Но ничего не работает. this.setState() просто не анимирует компонент Switch. Я также пытался играть с this._switch._rctSwitch.setNativeProps({ value: nextProps.active }), но это тоже не работает (и пахнет из-за _rctSwitch).

class ViewWithSwitchInside extends React.Component {
    constructor(props) {
        super(props)
        this.toggle = this.toggle.bind(this);
        this.state = {
            active: props.active
        }
    }

    componentWillReceiveProps(nextProps) {
        if (this.state.active != nextProps.active) {
            this.setState({ active: nextProps.active })
        }
    }

    toggle() {
        let newValue = !this.state.active
        this.setState({
            active: newValue,
        })
        if (typeof this.props.onClick === 'function') {
            this.props.onClick(newValue)
        }
    }

    render() {
        return (
            <TouchableWithoutFeedback onPress={this.toggle}>
                <View>
                    <Text>{this.props.title}</Text>
                    <Switch value={this.state.active} />
                </View>
            </TouchableWithoutFeedback>
        )
    }
}

1 ответ

Вы не можете визуализировать только одного потомка от вашего родительского компонента. Даже если бы вы каким-то образом смогли изменить значение переменной, от которой зависит Switch, оно не будет отображаться, пока вы не выполните рендеринг родительского компонента.

Я попытался использовать глобальную переменную для установки значения переключателя, я также предотвратил повторный рендеринг родительского компонента, используя shouldComponentUpdate() которые вы можете прочитать больше здесь

Это мои результаты:

Это начальное состояние моего приложения. Для этой глобальной переменной задано значение false, а родительский компонент уже обработан.

Теперь я изменяю глобальную переменную на true, нажав на View вокруг Switch и это меняется

Но визуально ничего не меняется, изменилась только переменная, а не переключатель.

Я тогда меняю state (несущественное изменение Switch компонент), нажав "Re-render" текст в нижней части экрана, и это происходит:

Результат повторного рендеринга

Это код приложения выше:

var isActive = false; //global variable
class Test extends Component {
  constructor(props) {
    super(props);
    this.state={active:false, irrelevantState: true};
  }

  test(foo){
    console.log("Attempting to change", foo);
    isActive = foo;
  }

  shouldComponentUpdate(nextProps, nextState){
    if(this.state.active != nextState.active){//If the new state is different than the previous, stop rendering.
      this.test(nextState.active);
      return false;
    }else { //else, re-render everything
      return true;
    }
  }

  render(){
    console.log("Test re-render");
    return(
      <View style={{flex:1}}>
        <TouchableOpacity onPress={()=>{this.setState({active:!this.state.active})}} style={{flex:1, marginTop:20}}>
          <Text>Test Component</Text>
          <Switch value={isActive}/>
        </TouchableOpacity>
        <TouchableOpacity onPress={()=>{this.setState({active:true})}} style={{flex:1, marginTop:20}}>
          <Text>Test Component</Text>
          <Switch value={isActive}/>
        </TouchableOpacity>
        <TouchableOpacity style={{height:20}} onPress={()=>this.setState({irrelevantState:false})}>
          <Text> Re-render</Text>
        </TouchableOpacity>
      </View>
    )
  }
}

Лучше всего найти умный способ перерисовки только тогда, когда this.state.active и другие необходимые состояния для вашего приложения для изменения функций, игнорируя другие изменения.

Другие вопросы по тегам