.setState不是React Native中的函数

时间:2017-08-22 03:34:54

标签: javascript mobile react-native

我已经通过同样的问题浏览了许多其他主题,但似乎没有人能找到我正在寻找的解决方案。我按照了YouTube的教程(Fullstack Development是频道,它是如何在28分钟内制作游戏)。我的主要代码如下:

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

import Enemy from './app/components/Enemy';

export default class Blox extends Component {

  constructor(props){
    super(props);
    this.state = {
      movePlayerVal: new Animated.Value(40),
      playerSide:'left',
      points: 0,

      moveEnemyVal: new Animated.Value(0),
      enemyStartposX: 0,
      enemySide: 'left',
      enemySpeed: 4200,

      gameOver: false,

    };
  }


  render() {
    return (
      <Image source = {require('./app/img/bg.png')} style={styles.container}>

      <View style= {{ flex:1, alignItems: 'center', marginTop: 80 }}>
          <View style={styles.points}>
              <Text style={{ fontWeight: 'bold', fontSize: 40 }}>{this.state.points}</Text>
          </View>
      </View>

          <Animated.Image source={require('./app/img/car.png')}
          style = {{
            height:100,
            width:100,
            position:'absolute',
            zIndex:1,
            bottom: 50,
            resizeMode: 'stretch',
            transform: [
              { translateX: this.state.movePlayerVal }
            ]
          }}></Animated.Image>

          <Enemy enemyImg={require('./app/img/enemy.png')}
          enemyStartposX={this.state.enemyStartposX}
          moveEnemyVal={this.state.moveEnemyVal} />

          <View style={styles.controls}>
              <Text style = {styles.left} onPress={ () => this.movePlayer('left') }> {'<'} </Text>
              <Text style={styles.right} onPress={ () => this.movePlayer('right') }> {'>'} </Text>
          </View>

      </Image>
    );
  }

  movePlayer(direction) {

    //move player right
    if (direction == 'right') {
      this.setState({ playerSide: 'right' }); //issue with setState being used as a function (from lines 78-124)

      Animated.spring(
        this.state.movePlayerVal,
        {
          toValue: Dimensions.get('window').width = 140,
          tension: 120,

        }
      ).start();

    } else if (direction == 'left') {
      this.setState({ playerSide: 'left' });

      Animated.spring(
        this.state.movePlayerVal,
        {
          toValue: 40,
          tension: 120,

        }
      ).start();
    }

  }

  componentDidMount() {
    this.animateEnemy();
  }

  animateEnemy() {

    this.state.moveEnemyVal.setValue(-100);
    var windowH = Dimensions.get('window').height;

    //Generate left distance for enemy
    var r = Math.floor(Math.random() * 2) * 1;

    if (r == 2) {
      r = 40;
      this.setState({ enemySide: 'left' });
    } else {
      r = Dimensions.get('window').width = 140;
      //Enemy is on the right
      this.setState = ({ enemySide: 'right' });
    }
      this.setState({ enemyStartposX: r });  //issue with this

    //Interval to check for collision each 50 ms
    var refreshIntervalId;
    refreshIntervalId = ( () => {

      //Collision logic

      //If enemy collides with player and they are on the same side
      //and the enemy has not passed the player safely
      if (this.state.moveEnemyVal._value > windowH - 280 && this.state.moveEnemyVal._value < windowH -180 && this.state.playerSide == this.state.enemySide) {

        clearInterval(refreshIntervalId)
        this.setState({ gameOver: true });
        this.gameOver();

      }

    }, 50);

    //Increase enemy speed each 20th second
    setInterval ( () => {
      this.setState({ enemySpeed: this.state.enemySpeed - 50 })
    }, 20000);

    //Animate the enemy
    Animated.timing(
      this.state.moveEnemyVal,
      {
        toValue: Dimensions.get('window').height,
        duration: this.state.enemySpeed,
      }
    ).start(event => {
      //if no enemy collision is detected, restart enemy animation
      if (event.finished && this.state.gameOver == false) {
          clearInterval(refreshIntervalId);
          this.setState({ points: ++this.state.points });
          this.animateEnemy();
      }

    });

  }

  gameOver() {
    alert('You lost big time!');
  }

}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    position: 'relative',
    resizeMode: 'cover',
  },
  points: {
      width: 80,
      height: 80,
      backgroundColor: '#fff',
      borderRadius: 100,
      alignItems: 'center',
      justifyContent: 'center',
    },
    controls: {
      alignItems: 'center',
      flexDirection: 'row',
    },
  right: {
    flex: 1,
    color: '#fff',
    margin: 0,
    fontSize: 60,
    fontWeight: 'bold',
    textAlign: 'left'
  },
  left: {
    flex: 1,
    color: '#fff',
    fontSize: 60,
    fontWeight: 'bold',
    textAlign: 'right'
  },
});

我还有一个看起来像这样的敌人类:

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

export default class Enemy extends Component {
  render() {
    return (
        <Animated.Image source={this.props.enemyImg}
          style = {{
            height:100,
            width:100,
            position:'absolute',
            resizeMode: 'stretch',
            left: this.props.enemyStartposX,
            transform: [
              { translateY: this.props.moveEnemyVal },
            ]
          }}></Animated.Image>
        );
    }
}

我通过XDE世博会运行这个,当我构建它时,它起作用了。然而,一旦我开始编码动画,世博会变红了,说我在第124行(在App.js中)有一个错误,.setState不是一个函数,它是一个对象。我评论了它,它告诉我在我的App.js文件的第78行中有同样的错误。你能告诉我.setState是什么,以及如何解决这个错误?感谢。

3 个答案:

答案 0 :(得分:0)

您应该将movePlayer函数绑定到构造函数中的适当范围:

constructor() {
   this.movePlayer = this.movePlayer.bind(this);
}

答案 1 :(得分:0)

我认为您的问题是如何处理方法回调。您只需在构造函数中bind方法movePlayer()animateEnemy(),如:

constructor(props) {
super(props);
this.state = {
  movePlayerVal: new Animated.Value(40),
  playerSide:'left',
  points: 0,

  moveEnemyVal: new Animated.Value(0),
  enemyStartposX: 0,
  enemySide: 'left',
  enemySpeed: 4200,

  gameOver: false,

};

// This binding is necessary to make `this` work in the callback
this.movePlayer = this.movePlayer.bind(this);
this.animateEnemy = this.animateEnemy.bind(this);

}

也许你可以在this中的ReactNative中深入了解你的句柄方法。

我希望我的回答可以帮到你..

答案 2 :(得分:0)

您的animateEnemy函数中的setState调用错误。这就是你收到错误信息的原因。

animateEnemy() {

  ...

  if (r == 2) {
    r = 40;
    this.setState({ enemySide: 'left' });
  } else {
    r = Dimensions.get('window').width = 140;
    // Enemy is on the right
    // this.setState = ({ enemySide: 'right' }); // This is wrong
    this.setState({ enemySide: 'right' });
  }

  ...

}

如果用箭头函数animateEnemy = () => { ... }更改所有函数会更好。通过这种方式,您无需在构造函数中手动绑定它。