-
230113 30분 TIL forEach의 return하루 30분 TIL 2023. 1. 13. 14:32
1. forEach 안에서 return/ breack 처리 ?!
상황
아래의 코드를 리팩터링 하고자 했다.
useEffect(() => { if (!Object.keys(QUIZ_TASTE_DESCRIPTION).find((key: string) => title?.includes(key))) { return setTasteData(initialTasteData); } for (const [key, value] of Object.entries(QUIZ_TASTE_DESCRIPTION)) { if (title?.includes(key)) { setTasteData(value); } } }, [title]);
QUIZ_TASTE_DESCRIPTION을 순회하는건 데 두 번씩이나 loop 할 필요 있을까? 한번으로 되지 않을까 라는 의문에서 시작됐다.
forEach문으로 조회시 가능하지 않을까 라는 생각이 들어 시도해 보았다.
useEffect(() => { const QUIZ_TASTE_DESCRIPTION_KEYS_ARRAY = Object.keys(QUIZ_TASTE_DESCRIPTION); const handleTasteData = (taste: string, index: number) => { if (title?.includes(taste)) { console.log('@@here!'); return setTasteData(QUIZ_TASTE_DESCRIPTION[taste]); } if (index + 1 === QUIZ_TASTE_DESCRIPTION_KEYS_ARRAY.length) { console.log('@@here2!'); return setTasteData(initialTasteData); } }; QUIZ_TASTE_DESCRIPTION_KEYS_ARRAY.forEach(handleTasteData); }, [title]);
의도한 건 includes 조건이 걸렸을 때 멈추고 마지막 index에서 tasteData를 initalTasteData로 리셋시키는 것이었다.
하지만 의도와 달리 if문에서 조건이 걸리더라고 멈추지 않았고 tasteData가 initalTasteData로 리셋이 됐다.
그래서 forEach 메소드가 얼리 리턴이 되는 줄 알고 그렇게 썼던 것 같은데 작동이 되지 않아 찾아봤다
아래 코드를 보자
const arr = [1,2,3,4,5]; arr.forEach((value) => { if(value == 3) return; console.log(value); }); // 기대 실제 // 1 1 // 2 2 // 3 4 // 5
기대한 바는 3에서 멈추는 것인데 4, 5까지 나오는 것을 알 수 있다.
아 생각해보니 이전에 썼을 때 해당 차수(index)에서 리턴 시키고 싶을 때 사용을 했구나! 기억이 났다.
그렇다면 위의 경우 어떻게 해야할 까?
for - of를 쓴다면 ?
for(const taste of Object.keys(QUIZ_TASTE_DESCRIPTION)) { if (title?.includes(taste)) { setTasteData(QUIZ_TASTE_DESCRIPTION[taste]); break; } setTasteData(initialTasteData); }
이렇게 쓸 때의 문제는 얼리 break 되지 않은 이상 setTasteData가 매번 실행되어 리렌더링이 계속될 것이다.
그렇다면 if문에서 만났을때 조기 breack도 되면서 마지막 차수일 때만 가능하게 하는 유일한 방법은 for문 밖에 없다!
const QUIZ_TASTE_DESCRIPTION_KEYS_ARRAY = Object.keys(QUIZ_TASTE_DESCRIPTION); for (let i = 0; i < QUIZ_TASTE_DESCRIPTION_KEYS_ARRAY.length; i++) { if (title?.includes(QUIZ_TASTE_DESCRIPTION_KEYS_ARRAY[i])) { setTasteData(QUIZ_TASTE_DESCRIPTION[QUIZ_TASTE_DESCRIPTION_KEYS_ARRAY[i]]); break; } if (i + 1 === QUIZ_TASTE_DESCRIPTION_KEYS_ARRAY.length) { setTasteData(initialTasteData); } }
의도했던 대로 동작을 한다!
하지만 효율성을 위해 더 어려운 코드가 된 느낌을 지울 수 없다.... ㅠ
그래서 처음의 코드로 다시 해야할 것 같다
라고 생각을 해서 동료와 얘기를 해보니 for of문 안의 조건문 안에서 return을 쓰면 해당 loop 뿐 아니라 밑의 코드까지 가지 않고 return이 된다고 한다.
useEffect(() => { for (const [key, value] of Object.entries(QUIZ_TASTE_DESCRIPTION)) { if (title?.includes(key)) { setTasteData(value); return; } } setTasteData(initialTasteData); }, [title]);
오호 훨씬 간단해졌다!!!
오늘의 결론
1. forEach 안에서 return이 되지 않는다.
2. for - of 문 안에서 break시 loop만 종료되고 return 시 일반 return 처럼 벗어날 수 있다.
'하루 30분 TIL' 카테고리의 다른 글
230209 30분 TIL (0) 2023.02.10 230116 30분 TIL (Proxy) (0) 2023.01.16 2301112 30분 TIL (a태그 noopener noreferrer / SOLID) (0) 2023.01.13 221220 TIL(useRef) (0) 2022.12.20 221214 TIL(useImperativeHandler) (0) 2022.12.14