개발노트

10. (3) hooks / useState 본문

React/basic

10. (3) hooks / useState

aloha2jh 2020. 7. 26. 15:04
import React ,{ useState } from 'react';

const ResponseCheck = () => {
    
  
    const [ color, setColor ] = useState('waiting');
    const [ message, setMessage ] = useState('클릭해서 시작');
    const [ result, setResult] = useState([]);
     
    // timeout; 
    // startTime;  //시작시간
    // endTime; //클릭한시간

    const onClickScreen = ()=>{
         
        if( color === 'waiting'){// waiting일때 클릭을 한 경우

            setColor('ready');
            setMessage('초록색이되면 클릭하시면 됩니다');

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

            } , Math.floor( Math.random()*1000 )+2000 )

        }else if( color === 'ready'){ // ready일때 클릭한 경우
            clearTimeout(this.timeout);
            setColor('waiting');
            setMessage('성급했다. 초록색된후에 클릭할것');

        }else if( color === 'now'){ // 클릭하라할때 클릭한 경우
          endTime = new Date(); ///////
          setColor('waiting');
          setMessage('클릭해서 시작하세요');
          setResult( (prevResult )=>{ return [ ...prevResult, endTime-startTime]} );
        }
    }
    const onReset = () => {
      setResult([]);
    }
    const getAverage = () => {
        
        return result.length === 0 ? null :
            <><p>평균시간: {result.reduce((a,c)=>a+c) / result.length} ms </p>
            <button onClick={ this.onReset }>리셋</button></>
    }
    
    return ( 
          <>
          <div id="screen" className={color} onClick={onClickScreen} >
          {message}
          </div>
          { getAverage()   }
          </> 
    )
}

export default ResponseCheck;

 

hook로 바꾸기

useState,  method-> const 에 arrayFunction ,  return

 

1. useState

(useState가 이해가안되서 좀더 찾아봄)

-react패키지의useState함수를 불러와서, 상태의 기본값을 인자로 넣어서 호출해주는것.인데

 

const [ color, setColor ] = useState('waiting');

위의 코드와 아래 코드는 같다

const colorState = useState('waiting');
const color = colorState[0];
const setColor = colorState[1];

useState('초기값') 함수를 호출하면 배열을 반환한다.

그 배열은 2개 아이템이 있다.

첫번째 배열[0] 은 상태값,

두 번째 아이템[1]은 상태값을 갱신해주는 함수.(이 함수호출시 리렌더링 된다)

 

 

그래서 배열 구조분해를 통해

const [ color, setColor ] = useState('waiting');

이런방식으로 써서, color가 현재 상태값, setColor로 상태값 업데이트로 사용.

 

(배열구조분해 예시)

const array = ['dog', 'cat', 'sheep'];
const [first, second] = array;
console.log(first, second); // dog cat

 

2. 메서드함수를 변수에담아주고

3. return

 

 

 

class component 의 filed (property) 값을 ref로 바꾼다.

(dom에 접근할때만 ref를 썻었지만) hooks에서는 this의 속성들을 ref로 표현한다.

// class component
timeout; 
startTime; 
endTime; 

// hooks
const timeout = useRef(null); 
const startTime = useRef();
const endTime = useRef();

 

-ref는 안에 current가 들어있기 때문에

값을 넣어줄때 , 가져올때 target.current

//class
this.startTime = new Date();

// hooks
starttime.current = new Date();

 

 

state vs ref ?

setState할때 return부분이 다시실행되지만,

useRef의 값들을 바꿀때는 return부분이 다시실행되지 않음

 

불필요한렌더링을 막기 위해,  값이바껴도 렌더링 시키고 싶지 않을경우(화면에는 영향을 미치고 싶지 않을때)

ref에 넣어서 쓰면 된다

 

 

 

 

import React ,{ useState , useRef } from 'react';

const ResponseCheck = () => {
    
  
    const [ color, setColor ] = useState('waiting');
    const [ message, setMessage ] = useState('클릭해서 시작');
    const [ result, setResult] = useState([]);
     
    const timeout = useRef(null); 
    const startTime = useRef();
    const endTime = useRef();

    const onClickScreen = ()=>{
         
        if( color === 'waiting'){// waiting일때 클릭을 한 경우

            setColor('ready');
            setMessage('초록색이되면 클릭하시면 됩니다');

            timeout.current = setTimeout(()=>{
              setColor('now');
              setMessage('click !!!');
                
                startTime.current = new Date();  //////

            } , Math.floor( Math.random()*1000 )+2000 )

        }else if( color === 'ready'){ // ready일때 클릭한 경우
            clearTimeout( timeout.current );
            setColor('waiting');
            setMessage('성급했다. 초록색된후에 클릭할것');

        }else if( color === 'now'){ // 클릭하라할때 클릭한 경우
          endTime.current = new Date(); ///////
          setColor('waiting');
          setMessage('클릭해서 시작하세요');
          setResult( (prevResult )=>{ return [ ...prevResult, endTime.current -startTime.current]} );
        }
    }
    const onReset = () => {
      setResult([]);
    }
    const getAverage = () => {
        
        return result.length === 0 ? null :
            <><p>평균시간: {result.reduce((a,c)=>a+c) / result.length} ms </p>
            <button onClick={ onReset }>리셋</button></>
    }
    
    return ( 
          <>
          <div id="screen" className={color} onClick={onClickScreen} >
          {message}
          </div>
          { getAverage()   }
          </> 
    )
}

export default ResponseCheck;

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

11. react life cycle  (0) 2020.07.26
10. (4)jsx 에서 for, if  (0) 2020.07.26
10. (2) ResponseCheck Game / setTimeout, if  (0) 2020.07.26
10. react 조건문  (0) 2020.07.25
9. props와 state연결하기  (0) 2020.07.25