2017-04-18 125 views
0

我注意到我的测试应用程序中有一些奇怪的行为。具有“componentWillReceiveProps”功能的我的组件是双重调用。点击按钮后应该只调用一次,但按奇怪顺序为双倍。 我有3个部分组成: 测试 - 启动组件 SetMessage - 从测试获得的道具,并传递给动画元件 动画 - 从SetMessage获得道具和dispaly反应原生,加倍呼叫组件

所以后点击按钮组件和功能应该是这样调用:

Test-> SetMessage(函数:reciveProps - > setMsg)然后 动画(函数:reciveProps-> showMsg)。

但在我的情况是:

测试 - > SetMessage(功能:reciveProps),然后动画(功能:reciveProps-> showMsg)然后 SetMessage(功能:changeMsg),然后 动画(功能:reciveProps-> showMsg)。

我想知道,如果是正常和罚款?如果没有,为什么会发生,以及如何解决它?

波纹管所有代码和日志屏幕。

Index.android.js:

import React, { Component } from 'react'; 
import { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    Navigator, 
    View 
} from 'react-native'; 

import Test from './app/components/Test/Test'; 
export default class testApp extends Component { 


    render(){ 
    return(
     <View style={{flex:1}}> 
      <Test/> 

     </View> 
    ) 
    } 

} 

AppRegistry.registerComponent('testApp',() => testApp); 

Test.js:

import React, { Component } from 'react'; 
import { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    Button, 
    View, 
    Animated, 
    Easing, 
    Switch, 
} from 'react-native'; 
import SetMessage from '../SetMessage/SetMessage'; 
export default class Test extends Component{ 

    constructor(){ 
     super(); 
     this.state = { 
      sendMsg:'plus' 
     } 
    } 
    change(){ 
     if(this.state.sendMsg==='plus'){ 
      this.setState({sendMsg:'minus'}); 
     }else{ 
      this.setState({ 
       sendMsg:'minus' 
      }); 
     } 

     console.log('Test com ') 
    } 

    render(){ 

     return (
      <View> 
       <Button 
        onPress={this.change.bind(this)} 
        title={'Start'} 
       /> 
       <SetMessage msg={this.state.sendMsg}/> 
      </View> 
     ) 
    } 

} 

AppRegistry.registerComponent('Test',() => Test); 

SetMessage.js:

import React, { Component } from 'react'; 
import { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    Button, 
    View, 
    Animated, 
    Easing, 
    Switch, 
} from 'react-native'; 
import Animation from '../Animation/Animation'; 
export default class SetMessage extends Component{ 

    constructor(){ 
     super(); 
     this.state = { 
      test:'', 
      sendMsg:'' 
     } 
    } 
    componentWillReceiveProps(nextProps){ 
     this.setState({ 
      test:nextProps.msg 
     },()=>this.setMsg()); 

     console.log('SetMessage F - ReciveProp'+this.state.sendMsg) 
    } 
    setMsg(){ 
     console.log('SetMessage F - Change Msg '+this.state.sendMsg); 
     this.setState({ 
      sendMsg:this.state.test 
     }) 
    } 
    render(){ 

     return (
      <View> 

       <Animation msg={this.state.sendMsg}/> 
      </View> 
     ) 
    } 

} 

AppRegistry.registerComponent('SetMessage',() => SetMessage); 

Animation.js

import React, { Component } from 'react'; 
import { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    View, 
    Animated, 
    Easing, 
    Switch, 
} from 'react-native'; 

export default class Animation extends Component{ 

    constructor(){ 
     super(); 
     this.state = { 
      msg:'', 
      bottom: new Animated.Value(-50) 
     } 
    } 
    componentWillReceiveProps(nextProp){ 
     console.log('Animation F - reciveProp'+this.state.msg); 
     this.setState({ 
      msg:nextProp.msg 
     },()=>this.showMsg()); 

    } 
    showMsg(){ 
     console.log('Animation F - showMsg '+this.state.msg); 
     if(this.state.msg!='') { 
      Animated.sequence([ 
       Animated.timing( // Animate over time 
        this.state.bottom, // The animated value to drive 
        { 
         toValue: 0, 
         duration: 500 // Animate to opacity: 1, or fully opaque 
        }), 
       Animated.delay(1000), 
       Animated.timing(this.state.bottom, // The animated value to drive 
        { 
         toValue: -50, 
         duration: 500 // Animate to opacity: 1, or fully opaque 
        }), 
      ]).start(); 
     } 
    } 


    render(){ 

     return (
      <View style={styles.mainCont}> 
       <Animated.View style={{ 
        height:50, 
        width:100+'%', 
        backgroundColor: 'rgba(0, 0, 0, 0.5)', 
        alignItems:'center', 
        justifyContent:'center', 
        position:'absolute', 
        bottom:this.state.bottom, 
       }}> 
        <Text style={styles.tekst}>{this.state.msg}</Text> 
       </Animated.View> 


      </View> 
     ) 
    } 

} 
const styles=StyleSheet.create({ 
    mainCont:{ 
     flex:1, 
     backgroundColor:'gray' 
    }, 
    container:{ 
     height:50, 
     width:100+'%', 
     backgroundColor:'#000', 
     alignItems:'center', 
     justifyContent:'center', 
     position:'absolute', 
     bottom:0 

    } 
}); 
AppRegistry.registerComponent('Animation',() => Animation); 

日志屏幕: enter image description here

谢谢。

回答

0

如果您检查的官方文档:https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops

你会发现声明“请注意,可能做出反应调用这个方法即使道具都没有改变,所以一定要比较当前和未来值... ”。我假设一些调用渲染是在一个父项上进行的,这个父项会在你的动画组件上调用一个重新渲染调用。因此,组件将会被调用。当使用上面的钩子时,我总是使用它:

componentWillReceiveProps(newprops) { 
    if(newprops.active === this.props.active) { return } 
    //if they are different do some stuff 
    } 
} 
+0

感谢您提供此信息。 – Klick