일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
29 | 30 | 31 |
- JavaScript
- 코딩테스트 고득점 Kit
- 자바스크립트
- 프로그래밍 언어론
- 데이터모델링과마이닝
- codesandbox
- useEffect
- 자바
- 리액트
- 코딩테스트 고득점 Kit 완전탐색
- 자바 공부
- React JS
- 백준
- useState
- Java
- vanillaJS
- NextJS
- 장고
- 디자인 패턴
- 프로그래머스
- react hook
- websocket
- 리액트 훅
- react firebase
- 컴퓨터 네트워크
- 프로그래머스 완전탐색
- design pattern
- 프로그래머스 자바
- 코틀린
- react
- Today
- Total
기록하는 개발자
[Redux] useDispatch hook 에러 해결기(Error: Invalid hook call) 본문
Error: Invalid hook call
위와같은 에러는 boardList 상태 관리를 위하여 react+typescript환경에 redux 적용 후 문제가 발생하였다.
구글링 결과 관련 해결 방법이 매우 많았지만 useDispatch에서 문제가 발생했던 나의 해결법을 써본다.
문제 발생 구간 : GetAlcohol.tsx
GetAlcohol.tsx의 작동 방식
1. 게시판 url인 '/board'로 라우팅되면 서버에 boardlist를 받기위한 get요청을 보낸다. 2. 이때 url에 query parameter로 필터링 정보를 붙여 전달한다. 3. 정상적으로 get이 전송되면 redux의 action을 통해 boardList를 저장한다. |
상태관리르 위해 redux를 적용하고 useSelector, useDispatch등의 hook을 사용하게 되면서 아래와 같은 오류가 발생하였다.
찾아본 결과 hook 내에서는 함수 호출이 불가능하며 컴포넌트 밖에서는 hook을 선언할 수 없는 등의 제한 사항이 있었다.
그러나 그러한 규칙들에 대한 해당사항이 없기 때문에 더욱 난처한 상황이었다.
내가 마주한 오류 메시지 react-dom.development.js:14906 Uncaught 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:
|
console 오류 메시지를 통해 내가 알 수 있는 것은
버튼 클릭 후 실행되는 Getalcohol내의 useDispatch에서 오류가 발생한다는 사실 뿐이었다.
이 때문에 useDispatch부터 invalid hook call, hook 에러 해결 등 며칠 간 구글링하며 무수히 많은 글을 마주했다.
그리고 드디어 오늘 오류 메시지가 사라졌다!!
useDispatch() 의 호출 과정
BoardFilter.tsx에 있는 버튼 클릭 → onClick 함수인 GetAlcohol 호출
→ GetAlcohol 함수의 최상단에서 useDispatch() 호출
위 과정에서 eventhandler가 결과적으로 직접 hook(useDispatch)을 호출하게 되는 점이 문제인 것 같았다.
돌고 돌아 왔지만 redux를 처음 적용하면서 도움을 받았던 블로그에서 useCallback이라는 도움을 받았고
구글링을 통해 얻은 정보를 조합하여 수정했더니 드디어 오류가 사라졌다.
아래는 수정 전 코드와 수정 후 코드이다.
수정 전
import React, { useState } from "react";
import "./boardFilter.css";
import axios from "axios";
import useGetAlcoholList from "./useGetAlcoholList";
const createSliderWithTooltip = Slider.createSliderWithTooltip;
const Range = createSliderWithTooltip(Slider.Range);
const BoardFilter = ([생략]) => {
...
return (
<div>
...
<button onClick={() => GetAlcoholList()}>찾기</button>
</div>
);
};
export default BoardFilter;
const GetAlcoholList = ([생략]) => {
const dispatch = useDispatch();
axios({
method: "GET",
url: '[생략]'
})
.then((res) => {
// 함수 내에서 dispatch를 직접 사용
dispatch(setBoardList(res.data));
})
.catch((err) => {
console.log("리스트 가져오기 에러", err);
});
};
export default GetAlcoholList ;
수정 후
import React, { useState } from "react";
import "./boardFilter.css";
import axios from "axios";
import useGetAlcoholList from "./useGetAlcoholList";
const createSliderWithTooltip = Slider.createSliderWithTooltip;
const Range = createSliderWithTooltip(Slider.Range);
const BoardFilter = ([생략]) => {
...
const { GetAlcoholList } = useGetAlcoholList(filterObj);
return (
<div>
...
<button onClick={() => GetAlcoholList()}>찾기</button>
</div>
);
};
export default BoardFilter;
function useGetAlcoholList([생략]) {
const dispatch = useDispatch();
//dispatch를 최상단 함수에서만 사용
// setBoardList : redux에서 작성한 action 함수
const setBoard = useCallback(
(boardItemList: type.boardItem[]) => dispatch(setBoardList(boardItemList)),
[dispatch]
);
const GetAlcoholList = () => {
axios({
method: "GET",
url: '[생략]'
})
.then((res) => {
setBoard(res.data);
})
.catch((err) => {
console.log("리스트 가져오기 에러", err);
});
};
return { GetAlcoholList };
}
useGetAlcoholList를 컴포넌트나 함수가 아닌 custom hook으로 작성하고 custom hook 내부에서 hook을 호출한다.
→ 이 때, useGetAlcoholList는 custom hook이기 때문에 반드시 소문자인 'use'로 시작해야만 한다.
setBoard 변수에 useCallback로 action인 setBoardList()를 가져온다.
이렇게 useDispatch를 GetAlcohol 함수 바깥에서 하면 더 이상 오류가 생길리가 없다!!!
구글링 : [ https://medium.com/@umioh1109/%EB%B2%88%EC%97%AD-js-bites-react-hook-is-called-in-a-function-which-is-neither-a-react-function-or-a-custom-33369d62ac84 ]
블로그 : [ https://devlog-h.tistory.com/33 ]
'Web > Redux' 카테고리의 다른 글
[Redux] React+TypeScript 환경에 Redux 적용하기 (0) | 2022.03.07 |
---|