调用组件内部的函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调用组件内部的函数相关的知识,希望对你有一定的参考价值。

我正在开发一个simon-says游戏,这是我的第一个React Native应用程序。

想法是根据我们当前的回合向玩家显示顺序,然后让玩家按下一个按钮,检查该按钮是否匹配给定的序列,如果是,则让用户再次按下,调用函数check再次。如果他在回合结束时没事,则我增加回合等,然后再次显示顺序。如果玩家失败,游戏将停止直到用户再次按下开始。

我不知道如何设置一个循环,使玩家可以按按钮直到回合结束,因为此功能仅在按下时才调用,所以我不知道如何控制它。

想法是根据我们当前的回合向玩家显示顺序,然后让玩家按下一个按钮,检查该按钮是否匹配给定的序列,然后让用户再次按下,再次调用功能检查。如果他没问题,那么我增加回合等,然后再次显示顺序。

所有这些都应该从第1轮到seq.length循环。

任何想法?我的代码如下。谢谢!

import React, {Component} from 'react';
import {StyleSheet, Text, View,TouchableOpacity, Button, Image} from 'react-native';
export default class App extends Component{ 
  constructor (props){
    super(props);
    this.flash=0
    this.round=1
    this.seq=[] 
    this.playerSeq=[] 
    this.win=false
    this.ok=true
    this.score=0
    this.state = {
      canPress: false,
      greenB: {
        backgroundColor: 'darkgreen'
      },
      yellowB: {
        backgroundColor: 'orange'
      },
      blueB: {
        backgroundColor: 'blue'
      },
      redB: {
        backgroundColor: 'red'
      }
    }
    this.play=this.play.bind(this)
    this.greenFlash=this.greenFlash.bind(this)
    this.blueFlash=this.blueFlash.bind(this)
    this.redFlash=this.redFlash.bind(this)
    this.playerTurn=this.playerTurn.bind(this)
    this.check=this.check.bind(this)
  }

  play(){
    this.seq=[1,2,3,1,4] //will be random, this is just for testing
    this.playerSeq=[] 
    this.flash=0
    this.round=1
    this.win=false
    this.ok=true
    this.score=0
    this.compTurn()
    this.setState({canPress: true})
  } 

  playerTurn(i){
    this.flash=0
    this.playerSeq[this.flash]=i
    this.setState({canPress: false})
    this.check()
  }

  check(){ 
    if (this.playerSeq[this.flash]==this.seq[this.flash]){
      if (this.playerSeq[this.flash]==1){
        this.greenFlash();
      }
      if (this.playerSeq[this.flash]==2){
        this.yellowFlash();
      }
      if (this.playerSeq[this.flash]==3){
        this.blueFlash();
      }
      if (this.playerSeq[this.flash]==4){
        this.redFlash();
      }
      this.flash++
      this.ok=true
      this.setState({canPress: true})
      if (this.flash==this.round){
        this.setState({canPress: false})
        this.round++
        }
      }
      else {
        this.ok=false;
      }
    }

    compTurn() {
      let intervalId = setInterval(()=> {
        if (this.flash==this.round) {
          clearInterval(intervalId);
        }
        else {
          if (this.seq[this.flash]==1){
            this.greenFlash();
          }
          if (this.seq[this.flash]==2){
            this.yellowFlash();
          }
          if (this.seq[this.flash]==3){
            this.blueFlash();
          }
          if (this.seq[this.flash]==4){
            this.redFlash();
          }
          this.flash++;
        }
      }
      , 1500);    
      this.setState({canPress: true})
      this.flash=0;
    }

  compTurn() {
      let intervalId = setInterval(()=> {
        if (this.flash==this.round) {
          clearInterval(intervalId);
        }
        else {
          if (this.seq[this.flash]==1){
            this.greenFlash();
          }
          if (this.seq[this.flash]==2){
            this.yellowFlash();
          }
          if (this.seq[this.flash]==3){
            this.blueFlash();
          }
          if (this.seq[this.flash]==4){
            this.redFlash();
          }
          this.flash++;
        }
      }
      , 1500);  

      this.setState({canPress: true})
      //this.userTurn=true;
      this.flash=0;
  }

  greenFlash(){
      setTimeout(() => {
        this.setState( {
            greenB:{
              ...this.state.style1, backgroundColor: 'lightgreen'
            }
            })
        }, 200);
      setTimeout(() => {
        this.setState( {
            greenB:{
              ...this.state.style1, backgroundColor: 'darkgreen'
            }
            })
        }, 1000);
  } 

  yellowFlash(){
    setTimeout(() => {
      this.setState( {
          yellowB:{
            ...this.state.style1, backgroundColor: 'yellow'
          }
          })
      }, 200);
    setTimeout(() => {
      this.setState( {
          yellowB:{
            ...this.state.style1, backgroundColor: 'orange'
          }
          })
        }, 1000);
  }

  blueFlash(){
    setTimeout(() => {
      this.setState( {
          blueB:{
            ...this.state.style1, backgroundColor: 'lightblue'
          }
          })
      }, 200);
    setTimeout(() => {
      this.setState( {
          blueB:{
            ...this.state.style1, backgroundColor: 'blue'
          }
          })
        }, 1000);
  }

  redFlash(){
    setTimeout(() => {
      this.setState( {
          redB:{
            ...this.state.style1, backgroundColor: 'pink'
          }
          })
      }, 200);
    setTimeout(() => {
      this.setState( {
          redB:{
            ...this.state.style1, backgroundColor: 'red'
          }
          })
        }, 1000);
  }

  render(){
    return (
      <View>
        <TouchableOpacity style={styles.playB}
        onPress={this.play}> 
        <Text style={{
          color:'white',
          height: 30,
          width:60,
          }}>START</Text>
        </TouchableOpacity>
        <TouchableOpacity style={[
          styles.greenB,
          this.state.greenB]} 
          onPress={this.state.canPress ? (()=> this.playerTurn(1)) : null}></TouchableOpacity>
        <TouchableOpacity style={[
          styles.yellowB,
          this.state.yellowB]} 
          onPress={this.state.canPress ? (()=> this.playerTurn(2)) : null}></TouchableOpacity>
        <TouchableOpacity style={[
          styles.blueB,
          this.state.blueB]} 
          onPress={this.state.canPress ? (()=> this.playerTurn(3)) : null}></TouchableOpacity>
        <TouchableOpacity style={[
          styles.redB,
          this.state.redB]} 
          onPress={this.state.canPress ? (()=> this.playerTurn(4)) : null}></TouchableOpacity>

          <Image
            source={{
              uri: 'https://images-eu.ssl-images-amazon.com/images/I/71pyavpLdIL.png'}}
            style={styles.icon}/>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  greenB:{
    padding: 5,
    height: 80,
    width: 80,  
    borderRadius:160,    
    position: 'absolute',
    top:380,
    left: 110
  },
  yellowB:{
    padding: 5,
    height: 80,
    width: 80,  
    borderRadius:160,   
    position: 'absolute',
    left: 110,
    top: 480

  },
  blueB:{
    padding: 5,
    height: 80,
    width: 80,  
    borderRadius:160,   
    position: 'absolute',
    top: 380,
    left: 210

  },
  redB:{
    padding: 5,
    height: 80,
    width: 80,  
    borderRadius:160, 
    position: 'absolute',
    left: 210,
    top: 480

  },
  playB:{
    padding: 10,
    marginLeft: 155,
    marginTop: 300,
    width: 100,
    backgroundColor: 'grey',
    height: 40,
    borderRadius: 40,
  },
  icon: {
    width: 200,
    height: 200,
    position: 'absolute',
    top: 50,
    left: 100, 
  }
});
答案

代替使用canPress状态,您应该设置count状态,每次单击该按钮,将count增大为1,然后使用countseq.length进行比较,然后将结果传递给disabled属性,就像这样<button disabled={count === seq.length}>

您可以在Codesandbox上查看演示。

Edit unruffled-black-pt8ie

[也许也可以给您一些有关将循环功能作为子组件的想法。 https://reactjs.org/docs/jsx-in-depth.html

下面的代码来自React Docs

// Calls the children callback numTimes to produce a repeated component
function Repeat(props) {
  let items = [];
  for (let i = 0; i < props.numTimes; i++) {
    items.push(props.children(i));
  }
  return <div>{items}</div>;
}

function ListOfTenThings() {
  return (
    <Repeat numTimes={10}>
      {(index) => <div key={index}>This is item {index} in the list</div>}
    </Repeat>
  );
}

您可以将TouchableOpacity包装到上面的Repeat之类的组件中,然后每次玩家开始新的回合,然后将更新的回合值作为道具传递给TouchableOpacity

以上是关于调用组件内部的函数的主要内容,如果未能解决你的问题,请参考以下文章

React - 错误:无效的钩子调用。 Hooks 只能在函数组件的主体内部调用

useStaticQuery:无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用

2C++ 的升级

错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。 (React-hooks React-native)

如何访问活动内部/从活动中的片段视图组件

错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。 【我还在用函数组件】