Error: Invalid hook call. Hooks can only be called inside of the body of a function component.
⛔문제상황
Next13 api 요청 함수를 만들다, 아래와 같이 에러가 발생했다.
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
🤔이유
사실 해당 에러의 원인 자체는 에러 문구에서 친절하게 안내해주고 있다.
Invalid hook call. Hooks can only be called inside of the body of a function component.
즉, 훅은 함수 컴포넌트의 본문 내에서만 호출할 수 있다는 거다.
원래 해당 함수를 컴포넌트 내부에서 작성하고자 했으나, 너무 길어져서 함수 외부 파일로 뺀거여서, 어떻게 해결해야 할지 고민이었다.🥲
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import {useRouter} from 'next/navigation';
const route = useRouter();
export const onSubmitEditLyrics = async (
formdata: TextAreaValue,
id: string,
lang: string
) => {
const loadingToast = toast.loading("가사를 수정 중입니다.")
try {
//생략//
route.push("/musicpt/" + id) 👈
} catch (err) {
//생략//
}
return
}
✅해결
custome Hook을 만들어 볼까? useRouter만을 위한 컴포넌트를 새로 만들어볼까? 등 여러 시도를 해보았으나, 가장 기본적인 방법으로 해결 되었다!😎
해당 함수를 호출하는 컴포넌트에서 useRouter 인스턴스를 함께 넘겨주면 되는 것이다.
이때 타입은 기본적으로 정의 된AppRouterInstance
타입을 사용했다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//함수를 사용하는 컴포넌트
export default function MusicLyricsEdit({ lang, id }: PropsType) {
//인스턴스 생성
const route = useRouter()👈
//해당 함수를 사용하는 컴포넌트
return (
<form
className="flex flex-col"
onSubmit={handleSubmit((data) =>
onSubmitEditLyrics(data, id, lang, route)👈
)}
>
//생략
</form>
)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//자막 수정
export const onSubmitEditLyrics = async (
formdata: TextAreaValue,
id: string,
lang: string,
route: AppRouterInstance👈
) => {
try {
//생략
route.push("/musicpt/" + id)👈
} catch (err) {
//생략
}
}
🔑마무리
방법을 알았으니, 이제 더 깔끔한 코드를 작성해보자.😎