React 스터디 4주차
🎮 웹 게임을 만들며 배우는 React
4주차: 반응속도 체크
1. 조건문
JSX 내부에서는 for(반복문)과 if(조건문)를 잘 사용하지 않는다.
조건문이 필요한 경우에는, 삼항 연산자를 사용한다.
{this.state.result.length === 0
? null :
<div>평균 시간: {this.state.result.reduce((a, c) => a + c) / this.state.result.length}ms</div>
}
또는, 보호 연산자의 사용이 가능하다.
{this.state.result.length !== 0
&&
<div>평균 시간: {this.state.result.reduce((a, c) => a + c) / this.state.result.length}ms</div>
}
2. 반응속도체크(class)
import React, { Component } from 'react';
class ResponseCheck extends Component {
state = {
state: 'waiting',
message: '클릭해서 시작하세요',
result: [],
};
timeout;
startTime;
endTime;
onClickScreen = () => {
const { state, message, result } = this.state;
if (state === 'waiting') {
this.setState({
state: 'ready',
message: '초록색이 되면 클릭하세요'
});
this.timeout = setTimeout(() => {
this.setState({
state: 'now',
message: '지금 클릭',
});
this.startTime = new Date();
}, Math.floor(Math.random() * 1000) + 2000); // 2~3초 랜덤
} else if (state === 'ready') { // 성급하게 클릭
clearTimeout(this.timeout);
this.setState({
state: 'waiting',
message: '성급하시네요! 초록색이 된 후에 클릭하세요.'
})
} else if (state === 'now') {
this.endTime = new Date();
this.setState((prevState) => {
return {
state: 'waiting',
result: [...prevState.result, this.endTime - this.startTime],
message: '클릭해서 시작하세요'
};
});
}
}
renderAverage = () => {
const { result } = this.state;
return this.state.result.length !== 0
&&
<div>평균 시간: {this.state.result.reduce((a, c) => a + c) / this.state.result.length}ms</div>
}
render() {
const { state, message } = this.state;
return (
<>
<div id="screen" className={this.state.state}
onClick={this.onClickScreen}>
{this.state.message}
</div>
{this.renderAverage()}
</>
)
}
}
export default ResponseCheck;
3. 반응속도체크(Hooks)
class를 Hooks로 전환할 때, 다른 부분들은 이전에 했던 것처럼 변경해주면 된다. 이때 신경써야 할 부분은 timeout / startTime / endTime이다. 이들은 this의 속성이었으므로 useRef를 통해 표현해 주어야 하고, 사용할 때에는 timeout.current
와 같이 작성한다.
이때 useRef()는
- .current 프로퍼티에 변경 가능한 값을 담고 있는 상자 역할을 함
- 순수 자바스크립트 객체를 생성하고 매번 렌더링을 할 때 동일한 ref 객체를 제공
- 가변값 유지에 있어 편리 (이때, .current 프로퍼티를 변형하는 것이 리렌더링을 발생시키지는 않는다. 즉, 값을 바뀌기는 하지만 화면에 영향을 미치게 하고 싶지 않을 때 Ref를 사용한다.)
와 같은 특징을 가지고 있다.
(참고: https://ko.reactjs.org/docs/hooks-reference.html#useref)
import React, { useState, useRef } from 'react';
const ResponseCheck = () => {
const [state, setState] = useState('waiting');
const [message, setMessage] = useState('클릭해서 시작하세요');
const [result, setResult] = useState([]);
const timeOut = useRef(null);
const startTime = useRef(); // 화면은 바꾸고 싶지 X
const endTime = useRef();
const onReset = () => {
setResult('');
};
const onClickScreen = () => {
if (state === 'waiting') {
setState('ready');
setMessage('초록색이 되면 클릭하세요');
timeOut.current = setTimeout(() => {
setState('now');
setMessage('지금 클릭');
startTime.current = new Date(); // Ref에 기록
}, Math.floor(Math.random() * 1000) + 2000); // 2~3초 랜덤
} else if (state === 'ready') { // 성급하게 클릭
clearTimeout(timeOut);
setState('waiting');
setMessage('성급하시네요! 초록색이 된 후에 클릭하세요.');
} else if (state === 'now') {
endTime.current = new Date();
setState('waiting');
setResult((prevResult) => {
return [...prevResult, endTime.current - startTime.current];
});
setMessage('클릭해서 시작하세요');
}
}
const renderAverage = () => {
return (result.length === 0
? null :
<>
<div>평균 시간: {result.reduce((a, c) => a + c) / result.length}ms</div>
<button onClick={onReset}>리셋</button>
</>)
}
return (
<>
<div id="screen" className={state}
onClick={onClickScreen}>
{message}
</div>
{renderAverage()}
</>
)
}
export default ResponseCheck;
4. return 내부에 for과 if 사용하기
JSX문에서 중괄호를 입력하면 Javascript 문법을 사용할 수 있는 것을 응용하여 return문 함수 내부에서 for과 if문을 사용할 수 있다.
return (
<>
<div id="screen" className={state}
onClick={onClickScreen}>
{message}
</div>
{() => {
if (result.length === 0) {
return null;
} else {
return <>
<div>평균 시간: {result.reduce((a, c) => a + c) / result.length}ms</div>
<button onClick={onReset}>리셋</button>
</>
}
}}
{renderAverage()}
</>
)
추가
1.
Uncaught TypeError: Cannot read properties of undefined (reading 'length')
return (result.length === 0
? null :
<>
<div>평균 시간: {result.reduce((a, c) => a + c) / result.length}ms</div>
<button onClick={onReset}>리셋</button>
</>)
이 코드에서 발생한 오류이다.
알고 보니 useState의 초깃값을 제대로 설정해 주지 않았다... 😑 사진과 같이 수정하니 제대로 동작하였다.
Author And Source
이 문제에 관하여(React 스터디 4주차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@abcriho/React-스터디-4주차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)