以编程方式对Native(使用Redux)进行动画切换 [英] React Native (with Redux) animate Switch programmatically

查看:91
本文介绍了以编程方式对Native(使用Redux)进行动画切换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个组件,里面有Switch组件。这整个组件都是可单击的。当您单击该组件时,它将触发调度(这将修改redux存储),并使该组件重新呈现。
我需要的是不重新渲染整个组件,而只是将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而闻起来)。

 类ViewWithSwitchInside扩展了React.Component {
构造函数(props){
超级(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>

}
}


解决方案

您不能仅从父组件中渲染一个孩子。即使您能够以某种方式更改Switch依赖的变量的值,也不会显示该变量,除非您重新渲染父组件。



为了使用全局变量设置切换器的值,我还使用 shouldComponentUpdate()阻止了父组件的重新渲染,您可以在



现在,通过在 Switch 周围点击 View ,将全局变量更改为true并且会更改





但视觉上没有任何变化,



然后更改状态(与<$无关的更改) c $ c>切换组件),方法是按屏幕底部的重新渲染文本,这会发生:





这是上面应用程序的代码:

  var isActive = false; //全局变量
类Test扩展了Component {
构造函数(props){
super(props ;;
this.state = {active:false,irrelevantState:true};
}

test(foo){
console.log(尝试更改,foo);
isActive = foo;
}

shouldComponentUpdate(nextProps,nextState){
if(this.state.active!= nextState.active){//如果新状态不同于先前状态,停止渲染。
this.test(nextState.active);
返回false;
} else {//否则,重新渲染所有内容
返回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>测试组件< / Text>
< Switch value = {isActive} /> ;
< / TouchableOpacity>
< TouchableOpacity onPress = {()=> {this.setState({active:true})}} style = {{flex:1,marginTop:20} }>
< Text>测试组件< / Text>
< Switch value = {isActive} />
< / TouchableOpacity>
< TouchableOpacity style = {{height:20}} onPress = {()=> this.setState({irrelevantState:false})}>
< Text>重新渲染< / Text>
< / TouchableOpacity>
< / View>

}
}

您最好的选择是找到一种仅在 this.state.active 和其他要求的状态下重新渲染的聪明方法您的应用可以更改功能,而无需考虑其他更改。


I have component which has Switch component inside. This whole component is clickable. When you click on this component, it fires dispatch (which modifies redux store) and causes this component to be re-rendered. What I need is to not re-render whole component but just to animate that Switch component to proper state.

Something like this

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

Any idea?

I find this pretty common use case and I know I will get to a lot of similar scenarios so I need this behaviour but I can't find any examples or solutions on web. Maybe I am just missing something.

Thanks

--- EDIT ---

I also tried this. I tried to disable updating with shouldComponentUpdate, I tried to set state only in willRecieveProps and/or toggle, even without toggle. I also tried playing with LayoutAnimation. But nothing works. this.setState() just doesn't animate Switch component. I also tried playing with this._switch._rctSwitch.setNativeProps({ value: nextProps.active }) but this doesn't work either (and it smells because of _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>
        )
    }
}

解决方案

You cannot render just one children from your parent component. Even if you were somehow able to change the value of the variable that the Switch depends on, it won't show unless you re-render the parent component.

I attempted to use a global variable to set the value of the switcher, I also prevented the re-rendering of the parent component using shouldComponentUpdate() which you can read more on here

This are my results:

This is the initial state of my app. That global variable is set to false, and the parent component was already rendered.

Now I change the global variable to true by tapping on the View around the Switch and it changes

But nothing changes visually, only the variable changed, not the switcher.

I then change the state (an irrelevant change to the Switch component) by pressing the "Re-render" text at the bottom of the screen and this happens:

This is the code of the App above:

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

Your best bet is to find a smart way to re-render only when this.state.active and other required states for your app to function change, disregarding other changes.

这篇关于以编程方式对Native(使用Redux)进行动画切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆