【问题标题】:.setState is not a function in React Native.setState 不是 React Native 中的函数
【发布时间】:2017-08-22 03:34:53
【问题描述】:

我已经查看了许多其他具有相同问题的线程,但似乎没有一个具有我正在寻找的解决方案。我遵循了 YouTube 上的教程(全栈开发是频道,它是如何在 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>
        );
    }
}

我正在通过 Expo XDE 运行它,并且在我构建它时,它工作正常。然而,一旦我开始编写动画,Expo 变成红色,并说我在第 124 行(在 App.js 中)有一个错误,即 .setState 不是一个函数,它是一个对象。我把它注释掉了,它告诉我我的 App.js 文件的第 78 行有同样的错误。你能告诉我 .setState 是什么,以及如何解决这个错误吗?谢谢。

【问题讨论】:

  • 尝试将movePlayer(direction) { 更改为movePlayer = () =&gt; { 词法绑定应该为您提供this 的适当范围
  • Sterling Archer,我按照您的建议在第 75 行更改了它,但它仍然给我错误,“this.setState 不是函数。(在 'this.setState({enemyStartposX: r} )', 'this.setState' 是 Object)"的一个实例"

标签: javascript mobile react-native


【解决方案1】:

您的 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 = () =&gt; { ... }更改所有函数会更好。这样就不用在构造函数中手动绑定了。

【讨论】:

  • 我已经在答案中写对了。 “this.setState = ({enemySide: 'right' });”应该改为“this.setState({enemySide:'right'});”
  • 谢谢。抱歉我没看到。现在它运行了。
  • 太棒了。很高兴它有帮助:)
【解决方案2】:

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

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

【讨论】:

  • 我将它放在构造函数内的 App.js 文件中的 this.state { } 之后,它给了我相同的错误消息。这就是我问这个问题的原因,因为其他论坛有这个解决方案,我试过没有运气。
【解决方案3】:

我认为你的问题是你如何处理方法回调。您只需在构造函数中使用 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 中的处理方法。

希望我的回答能帮到你..

【讨论】:

  • 感谢您的链接!但是,将这些语句放在构造函数中并不能解决我的问题。
  • 问题还是一样?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多