개발노트

10. (2) ResponseCheck Game / setTimeout, if 본문

React/basic

10. (2) ResponseCheck Game / setTimeout, if

aloha2jh 2020. 7. 26. 00:10

Rready상태 -> (클릭) -> 게임시작

기다려 상태 -> ( 2~3초 후 )

클릭해 상태 -> (클릭) -> 반응속도를 체크!

 

 

1. 기본 state, if 만들기

import React ,{Component} from 'react';

class ResponseCheck extends Component{
    
    state={
        color:'waiting',
        message:'클릭해서 시작',
        result:[],
    }
    
    onClickScreen = ()=>{
        
        const { color, result, message } = this.state;
        if( color === 'waiting'){// waiting일때 클릭을 한 경우
            this.setState({
                color:'ready',
                message:'초록색이되면 클릭하세요'
            });
            setTimeout(()=>{
                this.setState({
                    color:'now',
                    message:'클릭하세요',
                });
                 
            } , Math.floor( Math.random()*1000 )+2000 )
        }else if( color === 'ready'){ // ready일때 클릭한 경우
            // this.setState({
            //     color:'waiting',
            //     message:'성급했다. 초록색된후에 클릭할것'
            // })
            
        }else if( color === 'now'){ // 클릭하라할때 클릭한 경우
            this.setState({
                color:'waiting',
                message:'클릭해서 시작하세요',
                result:[]
            })
        }
    }
    getAverage = () => {
        const { result } = this.state;
        return result.length !== 0 && 
            <p>평균시간: {result.reduce((a,c)=>a+c) / result.length} ms </p>
    }
    render(){
        const { color, message } = this.state;
        return(
            <>
            <div id="screen" className={color} onClick={this.onClickScreen} >
            {message}
            </div>
            { this.getAverage()   }
            </>
        )
    }
}

export default ResponseCheck;

1. state값 설정후

2. 만약 결과값이 있으면 평균시간 구해주고

3. if문으로 상태값일때별로 setState처리 해주고

 

 

 

하지만 실행시 문제가 기다려상태인데 클릭했을 경우 다시 제일처음으로 돌아가야 하지만

setTimeout이 계속 걸려있어서 갑자기 클릭해 상태 가 실행되버림.

 

 

 

2. setTimeout 을 변수에담기

그래서 timeout을 초기화 하기 위해

(1) timeout을 만들어서 거기다 setTimeout을 넣어준다.

 timeout;
 ... 
 this.timeout = setTimeout(()=>{
                this.setState({
                    color:'now',
                    message:'클릭하세요',
                });

(2) clearTimeout에 timeout을 담아서 삭제.

 clearTimeout(this.timeout);

 

 

 

3. 걸린시간 재서 화면에보여주기

이제 클릭하세요 상태에서 사용자가 클릭할때까지 걸린시간을 재는법

시작시간, 클릭한시간 이 필요.

(시작시간은 바뀌는값이지만 state 에 넣을경우 렌더링일어나니까 밖에 선언해준다)

 

import React ,{Component} from 'react';

class ResponseCheck extends Component{
    
    state={
        color:'waiting',
        message:'클릭해서 시작',
        result:[],
    }
    
    timeout; 
    startTime;  //시작시간
    endTime; //클릭한시간

    onClickScreen = ()=>{
        
        const { color, result, message } = this.state;
        if( color === 'waiting'){// waiting일때 클릭을 한 경우
            this.setState({
                color:'ready',
                message:'초록색이되면 클릭하세요'
            });
            this.timeout = setTimeout(()=>{
                this.setState({
                    color:'now',
                    message:'클릭하세요',
                });
                
                this.startTime = new Date();  //////

            } , Math.floor( Math.random()*1000 )+2000 )
        }else if( color === 'ready'){ // ready일때 클릭한 경우
            clearTimeout(this.timeout);
            this.setState({
                color:'waiting',
                message:'성급했다. 초록색된후에 클릭할것'
            })
            
        }else if( color === 'now'){ // 클릭하라할때 클릭한 경우
            this.setState((prevState)=>{  //////
                return{
                    color:'waiting',
                    message:'클릭해서 시작하세요',
                    result:[ ...prevState.result, this.endTime - this.startTime ] ///////
                };
            })
            this.endTime = new Date(); ///////
        }
    }
    getAverage = () => {
        const { result } = this.state;
        return result.length !== 0 && 
            <p>평균시간: {result.reduce((a,c)=>a+c) / result.length} ms </p>
    }
    render(){
        const { color, message } = this.state;
        return(
            <>
            <div id="screen" className={color} onClick={this.onClickScreen} >
            {message}
            </div>
            { this.getAverage()   }
            </>
        )
    }
}

export default ResponseCheck;

 

 

+

reset 버튼 만들기

import React ,{Component} from 'react';

class ResponseCheck extends Component{
    
    state={
        color:'waiting',
        message:'클릭해서 시작',
        result:[],
    }
    
    timeout; 
    startTime;   
    endTime;  

    onClickScreen = ()=>{
        
        const { color, result, message } = this.state;
        if( color === 'waiting'){// waiting일때 클릭을 한 경우
            this.setState({
                color:'ready',
                message:'초록색이되면 클릭하세요'
            });
            this.timeout = setTimeout(()=>{
                this.setState({
                    color:'now',
                    message:'클릭하세요',
                });
                
                this.startTime = new Date();  

            } , Math.floor( Math.random()*1000 )+2000 )
        }else if( color === 'ready'){ // ready일때 클릭한 경우
            clearTimeout(this.timeout);
            this.setState({
                color:'waiting',
                message:'성급했다. 초록색된후에 클릭할것'
            })
            
        }else if( color === 'now'){ // 클릭하라할때 클릭한 경우
            this.setState((prevState)=>{  
                return{
                    color:'waiting',
                    message:'클릭해서 시작하세요',
                    result:[ ...prevState.result, this.endTime - this.startTime ] 
                };
            })
            this.endTime = new Date();  
        }
    }
    onReset = () => {  ////
        this.setState({
            result:[],
        });
    }
    getAverage = () => {  //////
        const { result } = this.state;
        return result.length === 0 ? null :
            <><p>평균시간: {result.reduce((a,c)=>a+c) / result.length} ms </p>
            <button onClick={ this.onReset }>리셋</button></>  //////
    }
    
    render(){
        const { color, message } = this.state;
        return(
            <>
            <div id="screen" className={color} onClick={this.onClickScreen} >
            {message}
            </div>
            { this.getAverage()   }
            </>
        )
    }
}

export default ResponseCheck;

 

평균시간인 result값을 비워주면, 평균시간이 리셋된다

당연하게도 true면 null 로 써야 화면에서 태그가 사라짐 ..

 

<html lang="ko">
    <head>
        <meta charset="utf-8">
        <title>game</title>
    </head>
    <style>
        #screen {
            width: 300px;
            height: 200px;
            text-align: center;
            user-select: none;
        }
        #screen.waiting {
            background-color: #5a985c;
        }
        #screen.ready {
            background-color: #dc7171;
            color: white;
        }
        #screen.now {
            background-color: #acd674;
        }
    </style>
    <body>
        <div id="root"></div>
        <script src="./dist/app.js"> 
        </script>
    </body>
</html>

'React > basic' 카테고리의 다른 글

10. (4)jsx 에서 for, if  (0) 2020.07.26
10. (3) hooks / useState  (0) 2020.07.26
10. react 조건문  (0) 2020.07.25
9. props와 state연결하기  (0) 2020.07.25
8. component 성능 최적화 /pureComponent, memo  (0) 2020.07.25