state가 변경되고, 다음 줄의 코드가 실행되도록 설정하기
유튜브를 따라 만드는 사이드 프로젝트를 진행하던 중 keyword를 누르면, keyword의 index 값은 변경된 값이 적용되지만 변경된 keyword의 값으로 데이터를 받아오지 못하는 오류가 발생
@원인
state를 변경하는 함수인 setState는 전부 비동기적으로 처리가 되기때문에, setState 함수가 오래걸리면 다음줄의 코드부터 실행됨
현재 키워드를 바꾸는 setCurrentIndex(idx)값보다 새로운 데이터를 가져오는 refetch()가 먼저 실행되고 있었음
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 변경 전 코드
const Home = () => {
const [currentTabIndex, setCurrentTabIndex] = useState(0);
return (
<KeywordContainer theme={theme}>
{keywords.map(({ keyword }, idx) => (
<Keyword
key={keyword}
onClick={() => {
setCurrentTabIndex(idx);
refetch();
}}
className={idx === currentTabIndex ? "isActive" : ""}
>
<p># {keyword}</p>
</Keyword>
))}
</KeywordContainer>
);
};
@해결하기
- useEffect를 사용해서 해당 state가 변경될 때만 useEffect()가 실행되도록 설정
- 키워드를 클릭하면 currentTabIndex가 변경되도록 설정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 변경 후 코드
const Home = () => {
const [currentTabIndex, setCurrentTabIndex] = useState(0);
// currentTabIndex가 변경될 때만 refetch함수가 실행
useEffect(() => {
refetch();
}, [currentTabIndex]);
return (
// 중략...
<KeywordContainer theme={theme}>
{keywords.map(({ keyword }, idx) => (
<Keyword
key={keyword}
onClick={() => setCurrentTabIndex(idx)}
className={idx === currentTabIndex ? "isActive" : ""}
>
<p># {keyword}</p>
</Keyword>
))}
</KeywordContainer>
);
};
@또 다른 오류
- useEffect()는 컴포넌트가 처음 렌더될 때 함께 실행되기 때문에 state가 변경될 때만 실행되어야하는 함수가 실행됨
- currentTabIndex가 변경될 때만 새로운 데이터를 가져오는 refetch()함수가 처음 렌더될 때 실행됨
해결: @useRef 훅을 사용해 첫 렌더될 때 실행 막기
- 첫 렌더될 때 isMounted의 값이 true 값으로 바뀌고, currentTabIndex가 변경될 때마다 useEffect가 실행됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// useRef()로 렌더 막기
const Home = () => {
const [currentTabIndex, setCurrentTabIndex] = useState(0);
const isMounted = useRef(false);
useEffect(() => {
if (isMounted.current) {
refetch();
} else {
isMounted.current = true;
}
}, [currentTabIndex]);
return (
// 중략...
<KeywordContainer theme={theme}>
{keywords.map(({ keyword }, idx) => (
<Keyword
key={keyword}
onClick={() => setCurrentTabIndex(idx)}
className={idx === currentTabIndex ? "isActive" : ""}
>
<p># {keyword}</p>
</Keyword>
))}
</KeywordContainer>
);
};
참고사이트
This post is licensed under CC BY 4.0 by the author.