eslint error 10가지 원인과 해결 방법
목차
1. 수정할 error 목록
2. 수정 내용
1. import/named
원인: 리팩토링 과정에서 type의 경로가 잘못 지정되었다.
해결: 경로를 올바르게 수정.
2. import/order
원인: 규칙에 따라 order가 재정렬 된 모양이 error 조건과 다른 듯 하다.
해결: NavHead 위로 Inter와 ReactNode 객체를 이동시킨다.
3. react/no-danger
원인: 태그에 존재하는 위험한 속성이니 조심해야한다. JS 스크립트를 삽입하는 XSS 공격에 노출될 수 있다.
해결:
1. 규칙을 warning하지 않도록 바꾼다.
2. 해당 라인을 무시하도록 한다.
4. react/jsx-no-useless-fragment
원인: 불필요한 fragment가 존재한다. child를 하나 이상 가지도록 해야한다.
해결: fragment가 부모가 아닌 형태로 만들어 준다.
5. react/no-unused-prop-types
원인: 사용되지 않은 prop-types 가 존재한다.
해결: 해당 props 타입을 조절해준다.
6. @typescript-eslint/no-unused-vars
원인: styles 를 import 해 놓고 사용하지 않았따.
해결: 해당 import 라인을 삭제해주면 된다.
7. consistent-return
원인: 함수가 아무것도 반환하지 않은 경우에 발생.
해결: return 을 빠뜨렸다면 return; 처럼 뭐가 됐든 함수를 return하여 종료시키도록 한다.
8. jsx-a11y/no-static-element-interactions
원인: div 태그에 onClick 이벤트를 주었다.
해결: onClick 이벤트는 button 태그에 적합하다. div를 button으로 바꾸고, type='button' 을 추가해준다.
9. no-redeclare
원인: 컴포넌트 이름과 타입 이름을 동일하게 작성했다.
해결: 타입 명은 모두 끝에 'Interface'를 붙이는 방식으로 통일한다.
10. import/no-cycle
원인:
=> props 타입을 해당 props를 사용하는 1번 컴포넌트 내에서 생성하고 export 하였다.
=> 2번 컴포넌트에서 해당 props를 import 하였다.
=> 2번 컴포넌트에서 1번 컴포넌트를 사용 중이다.
해결: type.ts 파일을 생성하여 props interface를 컴포넌트 외부로 빼준다.
- 그런데 근본적인 원인은 이게 아니다.
- type 을 어디에 저장하면 좋을지 몰라서 생긴 문제다.
진짜 해결: type 을 어떻게 관리해야하는지 공부해야 한다.
공부한 관리 방법 대로만 작성하면 이런 문제가 생기지 않을 것이다.
1. 수정할 error 목록
설정을 바꿨더니 수정할 내용이 많다. 하나씩 수정해보자.
./src/app/api/manage/category/route.ts
5:10 Error: CommonCategoryType not found in '@/containers/Editor/PostEditor' import/named
./src/app/layout.tsx
9:1 Error: next/font/google import should occur before import of @/containers/NavHead/NavHead import/order
13:1 Error: react import should occur before import of @/containers/NavHead/NavHead import/order
./src/components/buttons/GoPostCommentButton/GoPostCommentButton.tsx
6:61 Error: 'postId' PropType is defined but prop is never used react/no-unused-prop-types
./src/components/inputs/CustomInputs/CustomInputs.tsx
6:3 Error: 'className' PropType is defined but prop is never used react/no-unused-prop-types
27:3 Error: 'type' PropType is defined but prop is never used react/no-unused-prop-types
44:7 Error: Avoid non-native interactive elements. If using native HTML is not possible, add an appropriate role and support for tabbing, mouse, keyboard, and touch inputs to an interactive content element. jsx-a11y/no-static-element-interactions
./src/containers/CategoryEdit/components/AddMainCategoryForm/AddMainCategoryForm.tsx
9:8 Warning: 'styles' is defined but never used. @typescript-eslint/no-unused-vars
./src/containers/CategoryEdit/components/AddSubCategoryForm/AddSubCategoryForm.tsx
3:10 Error: CommonCategoryType not found in '@/containers/Editor/PostEditor' import/named
./src/containers/Comment/components/CommentForm/CommentForm.tsx
14:7 Error: 'CommentForm' is already defined. no-redeclare
14:7 Error: 'CommentForm' is read-only. no-import-assign
59:63 Error: Expected to return a value at the end of async arrow function. consistent-return
./src/containers/Editor/components/CategorySelector/CategorySelector.tsx
5:1 Error: Dependency cycle detected. import/no-cycle
5:33 Error: SubCategoryType not found in '../../PostEditor' import/named
./src/containers/Editor/PostEditor.tsx
8:1 Error: Dependency cycle via @/services/categoryFetch:3 import/no-cycle
11:1 Error: Dependency cycle detected. import/no-cycle
111:5 Error: Fragments should contain more than one child - otherwise, there’s no need for a Fragment at all. react/jsx-no-useless-fragment
./src/containers/MainPage/components/Slider/Slider.tsx
9:1 Error: Dependency cycle detected. import/no-cycle
./src/containers/MainPage/components/SliderItem/SliderItem.tsx
6:1 Error: Dependency cycle detected. import/no-cycle
./src/containers/ManageLikes/components/ManageLikeItem/ManageLikeItem.tsx
6:1 Error: 'dompurify' should be listed in the project's dependencies. Run 'npm i -S dompurify' to add it import/no-extraneous-dependencies
42:19 Warning: Dangerous property 'dangerouslySetInnerHTML' found react/no-danger
./src/containers/NavHead/components/UserMenu/UserMenu.tsx
36:7 Error: Avoid non-native interactive elements. If using native HTML is not possible, add an appropriate role and support for tabbing, mouse, keyboard, and touch inputs to an interactive content element. jsx-a11y/no-static-element-interactions
./src/hooks/useCategoryList.tsx
3:1 Error: Dependency cycle via @/containers/Editor/PostEditor:1 import/no-cycle
./src/services/categoryFetch.ts
1:1 Error: Dependency cycle via @/hooks/useCategoryList:8 import/no-cycle
1:10 Error: CommonCategoryType not found in '@/containers/Editor/PostEditor' import/named
2. 수정 내용
import/named
./src/app/api/manage/category/route.ts
5:10 Error: CommonCategoryType not found in '@/containers/Editor/PostEditor' import/named
./src/containers/CategoryEdit/components/AddSubCategoryForm/AddSubCategoryForm.tsx
3:10 Error: CommonCategoryType not found in '@/containers/Editor/PostEditor' import/named
./src/containers/Editor/components/CategorySelector/CategorySelector.tsx
5:33 Error: SubCategoryType not found in '../../PostEditor' import/named
1:1 Error: Dependency cycle via @/hooks/useCategoryList:8 import/no-cycle
1:10 Error: CommonCategoryType not found in '@/containers/Editor/PostEditor' import/named
원인: 리팩토링 과정에서 type의 경로가 잘못 지정되었다.
해결: 경로를 올바르게 수정.
import/order
./src/app/layout.tsx
9:1 Error: next/font/google import should occur before import of @/containers/NavHead/NavHead import/order
13:1 Error: react import should occur before import of @/containers/NavHead/NavHead import/order
원인: 규칙에 따라 order가 재정렬 된 모양이 error 조건과 다른 듯 하다.
해결: NavHead 위로 Inter와 ReactNode 객체를 이동시킨다.
// 이동 전 error가 발생한 지점
import NavHead from '@/containers/NavHead/NavHead';
import { Inter } from 'next/font/google';
import Footer from '@/containers/Footer/Footer';
import { ReactNode } from 'react';
// 이동 후 error 해결
import { Inter } from 'next/font/google';
import { ReactNode } from 'react';
import NavHead from '@/containers/NavHead/NavHead';
react/no-danger
./src/containers/ManageLikes/components/ManageLikeItem/ManageLikeItem.tsx
43:19 Warning: Dangerous property 'dangerouslySetInnerHTML' found react/no-danger
원인: 태그에 존재하는 위험한 속성이니 조심해야한다. 스크립트를 삽입하는 XSS 공격에 노출될 수 있다.
나는 dangerouslySetInnerHTML을 사용하여야 했기 때문에 XSS에 대비하기 위해서
dompurify의 sanitaizer 함수로 스크립트 실행을 방지하고 있지만, lint는 이를 인식하지 못하고 있다.
위험한 경고는 아닌 셈이다.
해결:
1. 규칙을 warning하지 않도록 바꾼다.
// .eslintrc.json
"rules": {
"react/no-danger": "off",
},
- 그러나 다른 사람이 이를 인지하지 못하고 작업을 dangerously 하게 만들 수도 있다.
2. 해당 라인을 무시하도록 한다.
// eslint-disable-next-line
주석을 추가하여 다음 라인의 경고를 무시하도록 할 수 있다.
const SanitizedInnerHTML = ({ contents }: { contents: string }) => {
return (
<div
// eslint-disable-next-line
dangerouslySetInnerHTML={{
__html: sanitize(contents.substring(0, 200)),
}}
/>
);
};
- html 태그 안에 직접 주석을 넣는 것이 바람직하진 않지만 적어도 나머지는 관리 대상에 포함된다.
react/jsx-no-useless-fragment
./src/containers/Editor/PostEditor.tsx
111:5 Error: Fragments should contain more than one child - otherwise, there’s no need for a Fragment at all. react/jsx-no-useless-fragment
원인: 불필요한 fragment가 존재한다. child를 하나 이상 가지도록 해야한다.
<>
{postId && loading ? (
// ...
)}
</>
- 이런 식으로 fragment 내에 곧바로 삼항연산자를 이용하려고 할 경우 나타나는 에러다.
해결: fragment가 부모가 아닌 형태로 만들어 준다.
<div className={styles.container}>
{postId && loading ? (
// ...
)}
</div>
react/no-unused-prop-types
./src/components/buttons/GoPostCommentButton/GoPostCommentButton.tsx
6:61 Error: 'postId' PropType is defined but prop is never used react/no-unused-prop-types
./src/components/inputs/CustomInputs/CustomInputs.tsx
6:3 Error: 'className' PropType is defined but prop is never used react/no-unused-prop-types
27:3 Error: 'type' PropType is defined but prop is never used react/no-unused-prop-types
원인: 사용되지 않은 prop-types 가 존재한다.
해결: 해당 props 타입을 조절해준다.
const GoPostCommentButton = ({ children }: { children: any; postId: string }) => {
// postId 삭제
const GoPostCommentButton = ({ children }: { children: any }) => {
설계했던 기능이 필요한가? 싶어 구현하지 않았었다. 그 잔재인 postId를 제거해주면 된다.
@typescript-eslint/no-unused-vars
./src/containers/CategoryEdit/components/AddMainCategoryForm/AddMainCategoryForm.tsx
9:8 Warning: 'styles' is defined but never used. @typescript-eslint/no-unused-vars
원인: styles 를 import 해 놓고 사용하지 않았다.
해결: 해당 import 라인을 삭제해주면 된다.
import { CustomInput } from '@/components/inputs/CustomInputs/CustomInputs';
// import styles from './AddMainCategoryForm.module.scss';
어차피 scss는 나중에 사용할 것이기 때문에 주석 처리만 하고 남겨뒀다.
consistent-return
./src/containers/Comment/components/CommentForm/CommentForm.tsx
59:63 Error: Expected to return a value at the end of async arrow function. consistent-return
원인: 함수가 아무것도 반환하지 않은 경우에 발생.
해결: return 을 빠뜨렸다면 return; 처럼 뭐가 됐든 함수를 return하여 종료시키도록 한다.
setState를 하면 return할 값이 없는 게 맞지만,
함수형 프로그래밍에서는 무언가를 반드시 return 해주는게 원칙이다.
jsx-a11y/no-static-element-interactions
./src/components/inputs/CustomInputs/CustomInputs.tsx
44:7 Error: Avoid non-native interactive elements. If using native HTML is not possible, add an appropriate role and support for tabbing, mouse, keyboard, and touch inputs to an interactive content element.
jsx-a11y/no-static-element-interactions
./src/containers/NavHead/components/UserMenu/UserMenu.tsx
36:7 Error: Avoid non-native interactive elements. If using native HTML is not possible, add an appropriate role and support for tabbing, mouse, keyboard, and touch inputs to an interactive content element.
jsx-a11y/no-static-element-interactions
원인: div 태그에 onClick 이벤트를 주었다.
<div className={`${styles.reset} ${value.length && styles.visible}`} onClick={clickInitialize}>
❌
</div>
해결: onClick 이벤트는 button 태그에 적합하다. div를 button으로 바꾸고, type='button' 을 추가해준다.
<button className={`${styles.reset} ${value.length && styles.visible}`} onClick={clickInitialize} type='button'>
❌
</button>
no-redeclare
import { CommentFormProps, CommentForm } from '@/types/post';
const CommentForm = ({
return //...
})
원인: 컴포넌트 이름과 타입 이름을 동일하게 작성했다.
해결: 타입 명은 모두 끝에 'Interface'를 붙이는 방식으로 통일한다.
const CommentForm = (props: CommentFormPropsInterface) => {
const { title, postId, userEmail, newUpdate, setNewUpdate, postCommentCount, setPostCommentCount } = props;
import/no-cycle
원인:
=> props 타입을 해당 props를 사용하는 1번 컴포넌트 내에서 생성하고 export 하였다.
=> 2번 컴포넌트에서 해당 props를 import 하였다.
=> 2번 컴포넌트에서 1번 컴포넌트를 사용 중이다.
해결: type.ts 파일을 생성하여 props interface를 컴포넌트 외부로 빼준다.
- 그런데 근본적인 원인은 이게 아니다.
- type 을 어디에 저장하면 좋을지 몰라서 생긴 문제다.
진짜 해결: type 을 어떻게 관리해야하는지 공부해야 한다.
공부한 관리 방법 대로만 작성하면 이런 문제가 생기지 않을 것이다.
상기된 10가지의 eslint 에러 해결을 해보았다.
굿잡