
상황
- UI가 다르지만 동일한 로직을 공유하는 컴포넌트들의 중복코드를 없애고자 로직을 분리하는 과정에서 발생한 에러이다.
- 로직을 util함수(JSX를 반환하지 않는 일반함수)로 분리한 후, 이를 사용할 컴포넌트에서 onClick이벤트 핸들러 함수로 넣어주고자 함.
문제의 코드
- 문제가 발생했던 유틸 함수
async function handleTableInteraction(e, tableId, errorDoorTableId) {
const isAdmin = localStorage.getItem('role') === 'admin';
//recoil 또한 hook으로 보기 때문에 일반 util함수에서 부를 수 없음.
const setSmallModal = useSetRecoilState(smallModalState);
const setTableModal = useSetRecoilState(modalState);
const showSmallModal = type => {
setSmallModal({ isOpen: true, type: type });
setTimeout(() => {
setSmallModal({ isOpen: false });
}, 2000);
};
const checkIfTableIsLocked = async tableId => {
const mapId = sessionStorage.getItem('mapId');
const isTableLocked = await getConfirmTableLocked(mapId, tableId);
return isTableLocked;
};
const checkForServingRobot = async () => {
const robotResult = await getDestinationRobot(
sessionStorage.getItem('userId')
);
return robotResult[0] === false ? robotResult[1] : false;
};
const openServeTableModal = (tableId, robotData) => {
setTableModal(
<ServeTableModal tableId={tableId} enableRobotData={robotData} />
);
};
//로직수행
if (isAdmin) {
const robotData = await checkForServingRobot();
openServeTableModal(tableId, robotData);
e.stopPropagation();
return;
}
const isTableLocked = await checkIfTableIsLocked(tableId);
if (isTableLocked) {
showSmallModal('tableLocked');
return;
}
if (errorDoorTableId?.includes(tableId)) {
showSmallModal('doorError');
return;
}
const robotData = await checkForServingRobot();
if (robotData === false) {
showSmallModal('noServing');
} else {
openServeTableModal(tableId, robotData);
e.stopPropagation();
}
}
export default handleTableInteraction;
문제 해결
- 공식문서를 읽어보자 ttps://legacy.reactjs.org/warnings/invalid-hook-call-warning.html
이 세가지 이유로 위와 같은 에러가 발생할 수 있다고 한다.
- You might have mismatching versions of React and React DOM.
- You might be breaking the Rules of Hooks.
- You might have more than one copy of React in the same app.
- 결론은 리액트 훅은 리액트 함수 컴포넌트 내부 또는 커스텀 훅 내에서만 호출해야 하는데.
- 내가 작성한 함수는 JSX를 반환하는 함수 컴포넌트도 아니며, 커스텀 훅의 규칙을 준수한 훅도 아니다.
- 따라서
useSetRecoilState
와 같은 훅이 들어가선 안된다. - 그래서 이 유틸함수를 사용하는 컴포넌트에
useSetRecoilState
를 옮겨준 후, 유틸함수에 인자로 넘겨주는 방식으로 코드를 수정하여 해결했다.
'웹개발 > Troubleshooting' 카테고리의 다른 글
[ESLint] no nested ternary, Do not nest ternary expressions 해결 (1) | 2023.12.21 |
---|

상황
- UI가 다르지만 동일한 로직을 공유하는 컴포넌트들의 중복코드를 없애고자 로직을 분리하는 과정에서 발생한 에러이다.
- 로직을 util함수(JSX를 반환하지 않는 일반함수)로 분리한 후, 이를 사용할 컴포넌트에서 onClick이벤트 핸들러 함수로 넣어주고자 함.
문제의 코드
- 문제가 발생했던 유틸 함수
async function handleTableInteraction(e, tableId, errorDoorTableId) {
const isAdmin = localStorage.getItem('role') === 'admin';
//recoil 또한 hook으로 보기 때문에 일반 util함수에서 부를 수 없음.
const setSmallModal = useSetRecoilState(smallModalState);
const setTableModal = useSetRecoilState(modalState);
const showSmallModal = type => {
setSmallModal({ isOpen: true, type: type });
setTimeout(() => {
setSmallModal({ isOpen: false });
}, 2000);
};
const checkIfTableIsLocked = async tableId => {
const mapId = sessionStorage.getItem('mapId');
const isTableLocked = await getConfirmTableLocked(mapId, tableId);
return isTableLocked;
};
const checkForServingRobot = async () => {
const robotResult = await getDestinationRobot(
sessionStorage.getItem('userId')
);
return robotResult[0] === false ? robotResult[1] : false;
};
const openServeTableModal = (tableId, robotData) => {
setTableModal(
<ServeTableModal tableId={tableId} enableRobotData={robotData} />
);
};
//로직수행
if (isAdmin) {
const robotData = await checkForServingRobot();
openServeTableModal(tableId, robotData);
e.stopPropagation();
return;
}
const isTableLocked = await checkIfTableIsLocked(tableId);
if (isTableLocked) {
showSmallModal('tableLocked');
return;
}
if (errorDoorTableId?.includes(tableId)) {
showSmallModal('doorError');
return;
}
const robotData = await checkForServingRobot();
if (robotData === false) {
showSmallModal('noServing');
} else {
openServeTableModal(tableId, robotData);
e.stopPropagation();
}
}
export default handleTableInteraction;
문제 해결
- 공식문서를 읽어보자 ttps://legacy.reactjs.org/warnings/invalid-hook-call-warning.html
이 세가지 이유로 위와 같은 에러가 발생할 수 있다고 한다.
- You might have mismatching versions of React and React DOM.
- You might be breaking the Rules of Hooks.
- You might have more than one copy of React in the same app.
- 결론은 리액트 훅은 리액트 함수 컴포넌트 내부 또는 커스텀 훅 내에서만 호출해야 하는데.
- 내가 작성한 함수는 JSX를 반환하는 함수 컴포넌트도 아니며, 커스텀 훅의 규칙을 준수한 훅도 아니다.
- 따라서
useSetRecoilState
와 같은 훅이 들어가선 안된다. - 그래서 이 유틸함수를 사용하는 컴포넌트에
useSetRecoilState
를 옮겨준 후, 유틸함수에 인자로 넘겨주는 방식으로 코드를 수정하여 해결했다.
'웹개발 > Troubleshooting' 카테고리의 다른 글
[ESLint] no nested ternary, Do not nest ternary expressions 해결 (1) | 2023.12.21 |
---|