проблема с таймером в React - PullRequest
       7

проблема с таймером в React

0 голосов
/ 11 октября 2019

Я делаю игру в React и внедряю для нее таймер. Вот код для основного компонента игры: (потерпите меня, я, возможно, мог бы использовать циклы на некоторых элементах JSX и т. Д.)

import React, {Component} from 'react';
import './Game.css';
import ScoreBoard from '../ScoreBoard/ScoreBoard';
import cardBack from '../../Images/back.png';
import j from '../../Images/j.jpg'; import j2 from '../../Images/j2.png';
import j3 from '../../Images/j3.png'; import j4 from '../../Images/j4.png';
import q from '../../Images/q.jpg'; import q2 from '../../Images/q2.jpg';
import q3 from '../../Images/q3.png'; import q4 from '../../Images/q4.png';
import k from '../../Images/k.jpg'; import k2 from '../../Images/k2.jpg';
import k3 from '../../Images/k3.png'; import k4 from '../../Images/k4.jpg';
import a from '../../Images/a.png'; import a2 from '../../Images/a2.png';
import a3 from '../../Images/a3.png'; import a4 from '../../Images/a4.png';

let dealCards = true;
let arrayRandom = [];
let curCard1;
let curCard2;
let counter = 1;
let id1;
let id2;
let canClick = true;
let score = 0;
let tries = 0;

class Game extends Component {

    state = {
        card0: cardBack, 
        card1: cardBack, 
        card2: cardBack, 
        card3: cardBack, 
        card4: cardBack, 
        card5: cardBack, 
        card6: cardBack, 
        card7: cardBack, 
        card8: cardBack, 
        card9: cardBack, 
        card10: cardBack, 
        card11: cardBack, 
        card12: cardBack, 
        card13: cardBack, 
        card14: cardBack, 
        card15: cardBack, 
        card16: cardBack, 
        card17: cardBack, 
        card18: cardBack, 
        card19: cardBack, 
        card20: cardBack, 
        card21: cardBack, 
        card22: cardBack, 
        card23: cardBack, 
        card24: cardBack, 
        card25: cardBack, 
        card26: cardBack, 
        card27: cardBack, 
        card28: cardBack, 
        card29: cardBack, 
        card30: cardBack, 
        card31: cardBack, 
        timer: 0
    }

    selected = (event) => {

        if (canClick === true) {
            let id = event.currentTarget.id; //card0
            let idString = id.toString(); //"card0"

            //ONLY ALLOW A CARD TO BE CLICKED IF ITS FACE DOWN
            if (this.state[idString] === cardBack) {

                idString = idString.replace(/card/g, ''); //"0"
                this.setState({[id] : arrayRandom[idString]});

                //FIRST PICK
                if (counter % 2 == 1) {
                    curCard1 = arrayRandom[idString].toString();
                    id1 = id;
                    counter++;
                //SECOND PICK
                } else {
                    //MAKE SURE A CARD DOESN'T GET SELECTED TWICE IN A ROW AND STAY FACE UP
                    if (id === id1) {
                        console.log("Select a different card for your second pick");
                    } else {
                        counter++;
                        tries++;
                        canClick = false; //STOP USER FROM SELECTING ANOTHER CARD
                        curCard2 = arrayRandom[idString].toString();
                        id2 = id;
                        setTimeout(() => {canClick = true}, 1000); //USER CAN PICK AGAIN IN 1 SEONCD
                        //IF THERE'S A MATCH - CARDS STAY FLIPPED, SCORE INCREASES BY 1
                        if (curCard1 == curCard2) {
                            score = score + 1;
                        //IF THERE'S NO MATCH - CARDS FLIP FACE DOWN AFTER A SECOND
                        } else {
                            setTimeout(() => {
                                this.setState({[id1]: cardBack});
                                this.setState({[id2]: cardBack});
                            }, 1000);
                        }
                    }
                }
            } else {
                console.log("This card has already been flipped, select another one");
            }
        }
    }

    setInterval( () => { this.setState({timer: this.state.timer + 1}); }, 1000);

    render() {

        //SORT THE CARDS IF THEY HAVEN'T BEEN SORTED YET
        if (dealCards === true) {
            dealCards = false;
            let arrayOrder = [j,j2,j3,j4,q,q2,q3,q4,k,k2,k3,k4,a,a2,a3,a4,j,j2,j3,j4,q,q2,q3,q4,k,k2,k3,k4,a,a2,a3,a4];  
            arrayRandom = arrayOrder.sort(sorter);  

            function sorter(a, b) {  
                return 0.5 - Math.random();
            }  

            console.log(arrayRandom);
        }



        return (
            <div id="gameBox">
                <ScoreBoard score={score} timer={this.state.timer} tries={tries}/>
                <img src={this.state.card0} id="card0" className="card" onClick={this.selected}/>
                <img src={this.state.card1} id="card1" className="card" onClick={this.selected}/>
                <img src={this.state.card2} id="card2" className="card" onClick={this.selected}/>
                <img src={this.state.card3} id="card3" className="card" onClick={this.selected}/>
                <img src={this.state.card4} id="card4" className="card" onClick={this.selected}/>
                <img src={this.state.card5} id="card5" className="card" onClick={this.selected}/>
                <img src={this.state.card6} id="card6" className="card" onClick={this.selected}/>
                <img src={this.state.card7} id="card7" className="card" onClick={this.selected}/>
                <img src={this.state.card8} id="card8" className="card" onClick={this.selected}/>
                <img src={this.state.card9} id="card9" className="card" onClick={this.selected}/>
                <img src={this.state.card10} id="card10" className="card" onClick={this.selected}/>
                <img src={this.state.card11} id="card11" className="card" onClick={this.selected}/>
                <img src={this.state.card12} id="card12" className="card" onClick={this.selected}/>
                <img src={this.state.card13} id="card13" className="card" onClick={this.selected}/>
                <img src={this.state.card14} id="card14" className="card" onClick={this.selected}/>
                <img src={this.state.card15} id="card15" className="card" onClick={this.selected}/>
                <img src={this.state.card16} id="card16" className="card" onClick={this.selected}/>
                <img src={this.state.card17} id="card17" className="card" onClick={this.selected}/>
                <img src={this.state.card18} id="card18" className="card" onClick={this.selected}/>
                <img src={this.state.card19} id="card19" className="card" onClick={this.selected}/>
                <img src={this.state.card20} id="card20" className="card" onClick={this.selected}/>
                <img src={this.state.card21} id="card21" className="card" onClick={this.selected}/>
                <img src={this.state.card22} id="card22" className="card" onClick={this.selected}/>
                <img src={this.state.card23} id="card23" className="card" onClick={this.selected}/>
                <img src={this.state.card24} id="card24" className="card" onClick={this.selected}/>
                <img src={this.state.card25} id="card25" className="card" onClick={this.selected}/>
                <img src={this.state.card26} id="card26" className="card" onClick={this.selected}/>
                <img src={this.state.card27} id="card27" className="card" onClick={this.selected}/>
                <img src={this.state.card28} id="card28" className="card" onClick={this.selected}/>
                <img src={this.state.card29} id="card29" className="card" onClick={this.selected}/>
                <img src={this.state.card30} id="card30" className="card" onClick={this.selected}/>
                <img src={this.state.card31} id="card31" className="card" onClick={this.selected}/>
            </div>
        );
    }
}

export default Game;

все работает, кроме моего таймера. эта строка является проблемой setInterval( () => { this.setState({timer: this.state.timer + 1}); }, 1000); Я хочу, чтобы она добавляла одну в секунду и отображала время в реальном времени. Есть два способа сделать это из того, что я могу догадаться.

  1. глобальная переменная let timer = 0;, а затем сразу после, вне класса, под глобалами setInterval( () => { timer++; }, 1000);. Я попробовал это, а затем просто использовал timer={timer} как опору в компоненте табло. Это работает, но обновляется только тогда, когда что-то еще отображается.
  2. состояние timer: 0. затем используйте setState, чтобы изменить его. проблема в том, что он начинает действовать очень странно, если я помещаю строку setInterval( () => { this.setState({timer: this.state.timer + 1}); }, 1000); в метод рендеринга (как будто она постоянно повторяет рендеринг), и я не могу найти способ запустить ее вне метода рендеринга, как метод вкласс.

какие-нибудь идеи о том, как я могу заставить это время работать в моем компоненте React?

1 Ответ

1 голос
/ 11 октября 2019

Вы можете запустить свой таймер внутри componentDidMount:

componentDidMount() {
    setInterval(() => {
      this.setState(({ timer }) => ({ timer: timer + 1 }));
    }, 1000);
}
...