反应setState没有在渲染中更新

时间:2020-07-06 20:11:37

标签: reactjs typescript

我使用了setInterval,并以此为基础显示计时器,但是setState不适用于该功能

this.setState({
                    updateTimer: minutes + ":" + seconds
                });

componentDidMount()中,我正在调用this.startTimer();函数,但是此函数不会更新setState,这里我已经上传了我的完整代码,有人可以检查我的代码并为我提供帮助解决此问题?

import * as React from "react";
import {GameDataStore, GameDataStorePayload} from "../../Global/DataStore/GameDataStore";
import {UserData, UserDataStore} from "../../Global/DataStore/UserDataStore";
import Grid from "@material-ui/core/Grid";
import {BlackCard} from "../../UI/BlackCard";
import Divider from "@material-ui/core/Divider";
import {Typography} from "@material-ui/core";
import {RevealWhites} from "./Components/Gameplay/RevealWhites";
import {ShowWinner} from "./Components/Gameplay/ShowWinner";
import {PickWinner} from "./Components/Gameplay/PickWinner";
import {LoadingButton} from "../../UI/LoadingButton";
import {PlayersRemaining} from "./Components/Gameplay/PlayersRemaining";
import {CardPlayTimeRemaining} from "./Components/Gameplay/CardPlayTimeRemaining";
import {ContainerProgress} from "../../UI/ContainerProgress";
import {cardDefsLoaded} from "../../Global/Utils/GameUtils";
import { id } from "apicache";

interface IGamePlayBlackProps
{
}

interface DefaultProps
{
}

type Props = IGamePlayBlackProps & DefaultProps;
type State = IGamePlayBlackState;

interface IGamePlayBlackState
{
    gameData: GameDataStorePayload;
    userData: UserData;
    buttonLoading: boolean;
    gameStarted: boolean;
    updateTimer : string;
    clearintervaltimer : string;
    is_started : string;
    intervalId : any;
}


export class GamePlayBlack extends React.Component<Props, State>
{
    public setTimer = '00:30';
    public setSeconds = 30;
    public interval_counter;
    constructor(props: Props)
    {
        super(props);
        this.state = {
            gameData: GameDataStore.state,
            userData: UserDataStore.state,
            buttonLoading: false,
            gameStarted: false,
            updateTimer: this.setTimer,
            clearintervaltimer : '',
            is_started : '0',
            intervalId : Function(),
        };
        localStorage.setItem('is_called','0');
        localStorage.setItem('is_called_show_winner_card','0');
        this.interval_counter = React.createRef<any>();
    }

    public componentDidMount(): void
    {
        GameDataStore.listen(data => this.setState({
            gameData: data
        }));

        UserDataStore.listen(data => this.setState({
            userData: data
        }));

        const me = this.state.gameData.game?.players?.[this.state.userData.playerGuid];
        const defsLoaded = cardDefsLoaded(this.state.gameData);

        if (!me || !this.state.gameData.game || !defsLoaded)
        {
            clearInterval(this.interval_counter.current);
        } else {
            let game_id = this.state.gameData.game.id;
            let chooserGuid = this.state.gameData.game.chooserGuid;
            let all_players = this.state.gameData.game.players;
            let all_player_id = Object.keys(all_players);

            //alert(gameData.game.chooserGuid);

            let filteredAry = all_player_id.filter(e => e !== this.state.userData.playerGuid);
            //let filteredAry  = all_player_id[0];

            console.log("user player guid:"+this.state.userData.playerGuid);
            console.log("guid:"+chooserGuid);   
            console.log("all players:"+all_player_id);  
            console.log("new array:"+filteredAry);

            let target_item = filteredAry.find((_, i, ar) => Math.random() < 1 / (ar.length - i));
            if(typeof target_item !== undefined && target_item!=null) {
                localStorage.setItem('target_turn',target_item);
            }


            localStorage.setItem('is_started','0');
            if(typeof this.state.gameData.game.id !== undefined && this.state.gameData.game.id!=null) {
                localStorage.setItem('game_id',this.state.gameData.game.id);
            }
            if(typeof this.state.gameData.game.chooserGuid !== undefined && this.state.gameData.game.chooserGuid!=null) {
                localStorage.setItem('chooserGuid',this.state.gameData.game.chooserGuid);
            }           
            let is_called = localStorage.getItem('is_called');
            if(is_called == "0") {
                this.startTimer();      
            }
        }
    }

    private onSelect = (winningPlayerGuid: string) =>
    {
        return GameDataStore.chooseWinner(this.state.userData.playerGuid, winningPlayerGuid);
    };

    private onClickStartRound = () =>
    {
        localStorage.setItem('is_started','1');
        clearInterval(this.interval_counter.current);
        
        
        this.setState({
            buttonLoading: true,
            gameStarted: true,
        });

        GameDataStore.startRound(this.state.userData.playerGuid)
            .finally(() => this.setState({
                buttonLoading: false,
                gameStarted: true,
            }));
    };

    private onClickSkipBlack = () =>
    {
        this.setState({
            buttonLoading: true
        });

        GameDataStore.skipBlack(this.state.userData.playerGuid)
            .finally(() => this.setState({
                buttonLoading: false
            }));
    };

    private skipPlayer = (game_string_id:any,target_turn:any,chooserGuid:any) => {
        return GameDataStore.skipPlayer(game_string_id,target_turn,chooserGuid);
    }

    public interval = () => {
        let timer =  this.setSeconds, minutes, seconds;
        let _self = this;    
        let is_started = this.state.is_started;
        if(is_started == "0") {
            let chooserGuid = localStorage.getItem('chooserGuid');
            let game_string_id = localStorage.getItem('game_id');
            let target_turn = localStorage.getItem('target_turn');
            let is_called = localStorage.getItem('is_called');

            if(typeof timer!==undefined && timer!=null) {
                minutes = parseInt(timer/60 as any,10);
                seconds = parseInt(timer%60 as any,10);
                minutes = minutes < 10 ? "0" + minutes : minutes;
                seconds = seconds < 10 ? "0" + seconds : seconds;
                
                console.log("test");
                console.log(minutes + ":" + seconds);
                
                this.setState({
                    updateTimer: minutes + ":" + seconds
                });

                if(timer == 0) {
                    //alert("start next round");
                    _self.skipPlayer(game_string_id,target_turn,chooserGuid);
                    clearInterval(this.interval_counter.current);
                }
                
                if (--timer < 0) {
                    //alert(timer);
                    clearInterval(this.interval_counter.current);
                } 
                this.setSeconds-=1;     
            }
        }
    }

    public clearTimer = () => {
        this.setState({is_started:'0'});
    }

    public startTimer = () => { 
        this.setState({is_started:'1'});
        console.log("called again");
        this.interval_counter.current = setInterval(this.interval, 1000);
    }

    public render()
    {
        const {
            gameData,
            buttonLoading
        } = this.state;
        

        const me = gameData.game?.players?.[this.state.userData.playerGuid];

        const defsLoaded = cardDefsLoaded(gameData);

        if (!me || !gameData.game || !defsLoaded)
        {
            return <ContainerProgress />;
        } else {
            let game_id = gameData.game.id;
            let chooserGuid = gameData.game.chooserGuid;
            let all_players = gameData.game.players;
            let all_player_id = Object.keys(all_players);
        }

        const {
            players,
            chooserGuid,
            roundCards,
            roundStarted,
        } = gameData.game;

        const roundCardKeys = Object.keys(roundCards ?? {});

        const remainingPlayerGuids = Object.keys(players ?? {})
            .filter(pg => !(pg in (roundCards ?? {})) && pg !== chooserGuid);

        const remainingPlayers = remainingPlayerGuids.map(pg => unescape(players?.[pg]?.nickname));

        const revealedIndex = this.state.gameData.game?.revealIndex ?? 0;
        const timeToPick = remainingPlayers.length === 0;
        const revealMode = timeToPick && revealedIndex < roundCardKeys.length;
        const hasWinner = !!gameData.game?.lastWinner;

        return (
            <>
                <div>
                    <PlayersRemaining/>
                </div>
                <Divider style={{margin: "1rem 0"}}/>

                {!roundStarted && (
                    <Typography style={{marginBottom: "1rem", textAlign: "center"}}>
                        <strong>You are the Card Captain!</strong>
                        <br/>
                        Read the card aloud, then click Start The Round. Once everyone plays, you will choose your favorite!<br/>
                        <span> {this.state.updateTimer}</span> Seconds
                    </Typography>
                )}

                {!timeToPick && roundStarted && (
                    <CardPlayTimeRemaining gameData={gameData}/>
                )}
                <Grid container spacing={2} style={{justifyContent: "center", marginTop: "1rem"}}>
                    {(!hasWinner) && (
                        <Grid item xs={12} sm={6} md={4} lg={3}>
                            <BlackCard packId={gameData.game?.blackCard.packId}>
                                {gameData.blackCardDef?.content}
                            </BlackCard>
                        </Grid>
                    )}
                    <RevealWhites canReveal={true}/>
                    <ShowWinner/>
                </Grid>
                {!roundStarted && (
                    <div style={{marginTop: "1rem", textAlign: "center"}}>
                        <LoadingButton loading={buttonLoading} color={"secondary"} variant={"outlined"} onClick={this.onClickSkipBlack}>
                            Skip Card
                        </LoadingButton>
                        <LoadingButton loading={buttonLoading} color={"secondary"} variant={"contained"} onClick={this.onClickStartRound} style={{marginLeft: "1rem"}}>
                            Start the round!
                        </LoadingButton>
                    </div>
                )}
                <PickWinner
                    canPick={true}
                    hasWinner={hasWinner}
                    onPickWinner={this.onSelect}
                    revealMode={revealMode}
                    timeToPick={timeToPick}
                />
            </>
        );
    }
}

0 个答案:

没有答案