React-native,doubled call components

时间:2017-04-18 16:27:38

标签: javascript reactjs react-native

我注意到我的测试应用中存在一些奇怪的行为。具有“componentWillReceiveProps”功能的组件是双重调用。按钮点击后应该只调用一次,但它的次数是奇怪的。 我有3个组件: 测试 - 启动组件 SetMessage - 从Test接收道具并传递给Animation组件 动画 - 从SetMessage和显示中接收道具

所以单击按钮后,组件和功能应该像这样调用:

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

但在我的情况下是:

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

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

Bellow所有代码和日志屏幕。

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

谢谢。

1 个答案:

答案 0 :(得分:0)

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

你会注意到语句“注意即使道具没有改变,React也可以调用这个方法,所以一定要比较当前和下一个值...”。我假设在一个父节点上进行了一些渲染调用,这使得在动画组件上调用重新渲染调用。因此,正在调用componentwillreceiveprops。我总是在使用上面的钩子时使用它:

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