React #4 _ 퀴즈 만들기(2)
React.StrictMode로 앱 개발을 해야 하는 이유...
우리가 build한 React 앱은 두 번 세 번 백 번 작동하더라도 에러 없이 똑같이 작동되어야 한다.
그래서 개발할 때 스트릭모드를 아래와 같이 설정해 놓고 개발을 하면
자동으로 두 번 실행을 시켜서 콘솔로그에 두번의 결과가 뜨는 것을 확인할 수 있고
이 덕분에 에러를 쉽게 발견할 수 있다.
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
위 StrictMode를 통해서 내 quiz 앱의 Timer 부분의 에러를 발견하였는데
setInterval 부분이 두 번 실행되면서 초기 100으로 설정해 놓은 값이 두 번 실행되어서
progress 바가 두배로 빠르게 닳는 에러를 발견했다.
에러를 해결하기 위해서는 Clean up 함수를 이용해야 한다. 만약 Interval이 끝나기 전에 재 실행 되거나 다음 문제로 넘어갔을 때
기존의 setInterval이 아직 끝나지 않았다면 progress바가 계속해서 이전의 값에 영향을 받기 때문에 Clean up 함수를 통해서 기존 Interval을 없애고 다시 시작해야 했다. 새로운 변수를 만들어 그 안에 설정 값을 넣어주고 return을 통해서 clear 하고 함수를 마무리하는 방법으로 문제를 해결할 수 있다.
useEffect(() => {
const timer = setTimeout(onTimeout, timeout);
return () => {
clearTimeout(timer);
};
}, [timeout, onTimeout]);
useEffect(() => {
const interval = setInterval(() => {
setRemainingTime((prevRemainingTime) => prevRemainingTime - 100);
}, 100);
return () => {
clearInterval(interval);
};
}, []);
또 하나의 새로운 발견 Key의 기능.
이제 useCallback을 사용하게 되면서 무분별한 함수 재생성을 막게 되었는데
내가 작성하는 코드에서 <QuestionTimer /> 는 Index가 새롭게 설정될 때마다 어쨌든 다시 랜더링이 되어야 하는데
지금 해당 코드에는 Index로부터 아무런 정보를 받아올 수 없어서 다음 문제로 넘어가도 즉, 인덱스의 상태가 바뀌어도
<QuestionTimer / >에서 알 수가 없다.
이럴 때 필요한 것이 바로 Key이다.
예를 들어 아래의 코드처럼 key를 주기만 해도 해당 값이 변화할 때, 컴포넌트가 목록의 일부가 아니더라도 그 변화에 맞춰서 오래된 컴포넌트는 지우고 새로운 걸 만들어낸다. 즉, 재 생성이 된다.
<QuestionTimer
key={activeQuestionIndex}
timeout={10000}
onTimeout={handleSkipAnswer}
/>