함수가 1급객체인 특성을 이용해 setInterval을 통한 Clean Up 작업을 전역상태로 처리한 코드를 정리하고자 한다.
구현해야 했던 기능은 React Native를 통해 만든 앱에서 게임이 진행되는 전체 시간초를 count해야했던 기능이였다.
먼저 기반이 되는 배경지식들부터 알아보자.
JS는 다른 언어들과 달리 함수를 1급객체로 취급한다.
그렇다면 1급 객체란 무슨 뜻일까?
JS Deep Dive에서는 다음과 같은 조건을 만족하는 객체를 1급객체라 말한다.
- 무명의 리터럴로 생성할 수 있다.(익명함수) 즉 런타임에 생성이 가능하다.
- 변수나 자료구조(객체, 배열)에 저장 할 수 있다.
- 함수의 매개변수에 전달 할 수 있다.
- 함수의 반환값으로 사용 할 수 있다.
JS의 함수는 일급객체이므로 값처럼 사용할 수 있다. 이런 일급객체의 특성은 JS로 하여금 함수형 프로그래밍을 가능하게 한다.
먼저 전체 문제를 해결한 전체 시간을 count 해야 했는데, 이를 위해 문제풀이가 시작되었을 때 useEffect를 통해 setInterval 이벤트를 등록해야 했다.
setInterval을 clean Up 하는 함수를 반환하는 클로저를 만들고, useEffect를 통해 컴포넌트가 마운트 되었을 때 Interval 이벤트를 등록한다. 클로저에서는 Interval마다 atom의 Duration Time을 update한다.
결과를 출력하고 이벤트 핸들러를 cleanUp 하는 과정은 마지막 Screen에서 이루어져야한다. 이를 위해 Recoil을 사용하였고, atom을 만들어 CleanUp Fn과 시간초를 atom에 저장했다.
//SecondScreen1.js
const SecondScreen1 = ({ navigation, route }) => {
const { params: { categoryId } } = route;
const [durationTime, setDurationTime] = useRecoilState(DurationTime);
const [durationCleanup, setDurationCleanup] = useRecoilState(DurationCleanUp);
...
const countClosure = () => {
const countProgress = setInterval(() => {
setDurationTime(current => current + 1);
}, 1000);
return () => clearInterval(countProgress);
};
useEffect(() => {
axios.get(`http://13.124.233.9:8080/categories/${categoryId}/questions?page=0`)
.then(({ data }) => {
console.log(data);
setfullItems(data);
setAnswerList(data.answers);
setLoading(false);
const arr = data.answers
arr.map((item) => {
if (item.isCorrect === true) {
setSolution(item.content)
}
})
})
.catch((err) => console.log(err))
const cleanUp = countClosure();
setDurationCleanup({ cleanUpFn: cleanUp });
}, []);
return(
...
)
//atom.js
import {
atom,
} from 'recoil';
export const DurationTime = atom({
key: 'DurationTime',
default: 0,
});
export const DurationCleanUp = atom({
key: 'DurationCleanup',
default: { cleanUpFn: '', }
})
// SecondScreen4.js
const SecondScreen4 = ({ navigation }) => {
const [durationCleanup, setDurationCleanup] = useRecoilState(DurationCleanUp);
...
useEffect(() => {
axios.get(`http://13.124.233.9:8080/categories/5/questions?page=3`)
.then(({ data }) => {
setfullItems(data);
setAnswerList(data.answers);
setLoading(false);
const arr = data.answers
arr.map((item) => {
if (item.isCorrect === true) {
setSolution(item.content)
}
})
})
.catch((err) => console.log(err))
return durationCleanup.cleanUpFn(); //
}, []);
// LastScreen.js
const LastScreen = ({ navigation }) => {
const [durationTime, setDurationTime] = useRecoilState(DurationTime);
useEffect(() => {
return () => setDurationTime(0);
}, [])
return (
...
<Text style={{ color: "#3498DB" }}>{durationTime}초</Text>가 걸렸어요
...
)
}
ref)
JS DeepDive 18장 함수와 일급 객체