cra + eslint(airbnb) extensions, no-unresolved 오류 해결

terminal
1
2
3
yarn create react-app . --template typescript
yarn eslint --init
yarn add -D eslint-config-airbnb@latest
  • cra + eslint(airbnb)
  • 이렇게 리액트 프로젝트를 시작했을 때,

import/extensions
import/no-unresolved
react/jsx-filename-extension

  • 이런 오류가 나온다
  • 오류가 뜨지 않도록 eslintrc를 설정해주자

eslintrc

eslintrc.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
// ...
"rules": {
"react/jsx-filename-extension": [
"error",
{ "extensions": [".ts", ".tsx"] }
],
"import/extensions": [
"error",
"ignorePackages",
{
"ts": "never",
"tsx": "never"
}
]
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".ts", ".tsx", ".js", ".jsx"]
}
}
}
}
  • 위처럼 설정해 주었다

참고

eslint ignorePatterns

린트하고 싶지 않은 디렉터리를 설정해줄 수 있다

  • 스토리북이 src 밑에 있어서 린트가 같이 적용되었다
  • eslint가 스토리북 디렉터리를 무시하도록 해보자
.eslintrc
1
2
3
4
{
// ...
"ignorePatterns": ["/src/stories/**/*"]
}
  • 루트 경로부터 표현해야 한다

참고

JSX is not defined.

eslint가 JSX를 못 알아먹는다

.eslintrc
1
2
3
4
5
6
{
"globals": {
"JSX": true
}
//...
}

eslint 빨간줄, 재시작

  • nodejs, javascript, typescript 등 어떤 카테고리에 넣어야할지 고민하다가 그냥 vscode에 넣었다

  • 왜냐하면 vscode를 재시작하는 게 중요 포인트이기 때문이다

  • ESLint: Restart ESLint Server 또는

  • developer: reload window 을 꼭 해주자

  • eslint config를 수정했으면 vscode창을 다시 실행한다
  • eslint config를 수정했는데, 린트가 동작하지 않는데, 뭐 때문에 동작하지 않는지 모른다면
  • yarn eslint tmp.ts 같은 명령을 사용해서 아웃풋을 확인한다
  • 그러면 어떤 패키지가 없어서, 어떤 유효하지 않은 설정을 사용해서 동작하지 않는다는 정보를 얻을 수 있다
  • 그리고 eslintrc에 들어가는 내용을 너무 다 세세히 알려고 하지 말자
  • 일단 동작하면 그러려니 하면 된다
  • 나중에 관련해서 더 세세하게 커스텀 하고 싶을 때만 알아보자

eslint 장점

  • 코딩 실력이 크게 늘었다?
  • eslint가 잡아주는 오류들을 수정하면서
  • js의 유용한 문법이나,
  • 불필요한 코드들을 많이 지울 수 있었다
  • 예를 들면, prefer-destructuring룰로 구조 분해 할당 같은 문법들을 알게 된다라던가
  • 반복문 안에서 비동기 함수를 await을 붙여 실행하는데,
  • 당시에는 비동기가 익숙하지 않아서 무조건 await을 붙여서 값을 바로 꺼내서 핸들 하기 급급했는데,
  • 린트가 Unexpected 'await' inside a loop. 에러를 뱉어줬다
  • 관련해서 검색하고 공부하고, Promise에 대해 자세히 공부해보고,
  • 결국 이전의 결과가 다음에 필요하지 않다면
  • Promise.all로 실행해서 병렬로 처리 후에 한 번에 결과를 받아서 핸들 한다던가
  • 선생님 같은 느낌으로 정말 도움이 많이 되었다

eslint rule 설정할 때

“off” or 0 - turn the rule off
“warn” or 1 - turn the rule on as a warning (doesn’t affect exit code)
“error” or 2 - turn the rule on as an error (exit code is 1 when triggered)

prettier와 함께쓰기

terminal
1
yarn add -D prettier eslint-config-prettier
  • eslint-config-prettier를 설치한다
  • eslint와 prettier같 충돌나는 룰을 disable해준다
eslintrc.json
1
2
3
4
5
6
7
8
9
10
11
12
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"react-app",
"react-app/jest",
"plugin:react/recommended",
"airbnb",
"prettier" // 여기 추가
],

참고

eslint --init 으로 쉽게 eslint 세팅하기

이전에 react eslint 관련해서 여러 글을 작성했다 (다 엄청난 삽질이었다…)

terminal
1
npx eslint --init
  • 위 명령으로 한 번에 해결
  • 방향키로 선택 선택 넘어가면, 알아서 환경을 세팅해준다

CRA와 eslint –init해서 프로젝트 세팅하는 과정

termial
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# CRA로 리액트 프로젝트 시작
yarn create react-app . --template typescript

# eslint --init 으로 eslint 세팅
yarn eslint --init
√ How would you like to use ESLint? · style
√ What type of modules does your project use? · esm
√ Which framework does your project use? · react
√ Does your project use TypeScript? · Yes
√ Where does your code run? · browser
√ How would you like to define a style for your project? · guide
√ Which style guide do you want to follow? · airbnb
√ What format do you want your config file to be in? · JSON
√ Would you like to install them now with npm? · No
  • 입맛대로 답변한다
  • 특히 마지막 Would you like to install them now with npm? 물음에는 No로 답변한다
  • No로 답변하고 필요한 종속성을 yarn으로 설치해준다
  • (Yes로 답변하면, npm으로 설치되며 package-lock.json이 생성된다)
terminal
1
2
3
4
5
6
7
8
9
10
11
# 콘솔에 적힌 종속성들을 복사해서 적절히 편집하고 실행한다
# 여러 버전들을 나열해서 알려주는데, 그중에서 최신 버전을 다운받았다
yarn add -D \
eslint-plugin-react@^7.21.5 \
@typescript-eslint/eslint-plugin@latest \
eslint-config-airbnb@latest \
eslint@^7.2.0 \
eslint-plugin-import@^2.22.1 \
eslint-plugin-jsx-a11y@^6.4.1 \
eslint-plugin-react-hooks@^4 \
@typescript-eslint/parser@latest
terminal
1
2
3
4
5
# eslint와 prettier를 함께 쓰려면 아래도 함께 설치한다
yarn add -D \
prettier \
eslint-plugin-prettier \
eslint-config-prettier

참고

eslint(react-hooks/exhaustive-deps) autofix

  • eslint(react-hooks/exhaustive-deps)
  • useEffect, useCallback 등 종속성을 가지는 훅에서 누락된 종속성을 알려준다

auto fix

  • 이전 버전에서는 autofix를 지원했는데,
  • 최신 버전은 지원하지 않는다
  • 나는 이전 버전을 사용해서 자동으로 종속성 업데이트해주는 것에 익숙하고 좋았었다
  • 그래서 autofix 활성화하는 법을 찾아보았다
  • auto fix를 활성화하려면 eslint config에 설정을 추가해준다
.eslintrc
1
2
3
4
5
6
7
8
9
10
11
12
{
// ...
"rules": {
// ...
"react-hooks/exhaustive-deps": [
"warn",
{
"enableDangerousAutofixThisMayCauseInfiniteLoops": true
}
]
}
}
  • enableDangerousAutofixThisMayCauseInfiniteLoops를 활성화한다

참고

tsconfig baseUrl eslint

tsconfig에 baseUrl을 ./src로 설정했다
그런데 eslint가 못 알아먹는다
알아먹도록 해보자

상황

  • 타입스크립트 프로젝트에서 npx eslint --init을 통해 eslint 환경을 구성했다
  • 그런데 tsconfig에 설정한 baseUrl을 eslint가 알아먹지 못했다

eslint-import-resolver-typescript 설치

terminal
1
yarn add -D eslint-import-resolver-typescript

eslintrc 수정

.eslintrc.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
// ...
"parserOptions": {
// ...
"project": "./tsconfig.json"
},
// ...
// https://github.com/import-js/eslint-plugin-import/issues/1485#issuecomment-535351922
"settings": {
"import/resolver": {
"typescript": {}
}
}
}
  • parserOptions.projectsettings.import/resolver.typescript에 위 내용처럼 추가한다
  • eslint config를 수정하면 항상 ESLint: Restart ESLint Server 또는 Developer: Reload Window을 꼭 해주자

참고

eslint prefer-destructuring

Use array destructuring

  • ???
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let time = 0;
const arrarr = [
[0, 1],
[1, 11],
[2, 21],
];
// ...

// error
time = arrarr[0][0];
// ok
[[time]] = arrarr; // 0

// error
time = arrarr[1][1];
// ok
[, [, time]] = arrarr; // 11
  • 홀리…
  • 배열과 오브젝트는 구조 분해 할당할 수 있다
  • 오브젝트의 경우 자주 사용하지만, 배열의 경우는 별로 사용해본적이 없다
  • 리액트를 쓰면서 useState에서 state와 setState함수를 받을 때 주로 사용했지,
  • 이렇게 이미 선언해서 쓰던 변수에 값을 덮어쓸 때 사용해서 약간 충격이다
  • 배열에 변수가 아닌 정적인 상수 인덱스를 통해서 꺼내는 경우 구조 분해 할당을 사용하라고 추천해줘서 알게 되었다
  • 근데 상수 인덱스가 너무 큰 경우에는 오히려 가독성이 떨어질 것 같다

참고

jest 'describe' is not defined

.eslintrc.json
1
2
3
4
5
6
7
{
"env": {
// ...
"jest": true
}
// ...
}
  • env에 추가해준다
  • ⚠️ 추가 해주고 F1 > eslint.restart 명령을 실행해 eslint를 재부팅한다

상황

  • jest를 eslint와 처음 사용해본다

eslint(no-undef)

‘describe’ is not defined.
‘test’ is not defined.
‘expect’ is not defined.

  • 위 에러가 나왔다

참고

react로 만들어본 퇴근시간 계산기

기능

메인 페이지

  • 목표 시각까지 남은 시간 계산
  • url param을 통해 목표 시각 세팅
  • 목표 시각이 지나면 퇴근하라는 메시지를 뛰움

about 페이지

  • 링크 공유 기능
  • 퇴근 시간 설정 기능
  • 자동 클립보드 복사

깃허브 페이지 spa 세팅

배경이미지 출처

해결한 문제들

gsap 적용안됨

Share.tsx
1
2
3
4
5
import { Power3, TimelineLite } from 'gsap';
import CSSPlugin from 'gsap/CSSPlugin'; // 추가

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const C = CSSPlugin; // 추가
  • 로컬에서는 애니메이션이 잘 실행되었는데, 빌드 후 애니메이션이 안 나오는 문제 해결

후기

  • 어느 정도 리액트에 익숙해진 것 같다
  • 주로 사용하는 패턴이 생긴 것 같다
  • 엄청 간단해 보이지만 이것저것 신경 쓴 것 같은데, 기록을 안 해놨다 ㅠㅠ
  • 나는 코드에 조금의 변화가 생겨도 커밋을 했었는데,,
  • 이번에는 커밋을 안 하고 한 번에 몰아서 마지막에 파일별로 커밋을 했다
  • 그래서 해결한 문제들이 기억이 잘 안 난다.. ㅠㅠ

신경 썼던 것들

input element

  • about 페이지에서는 링크를 생성하는 부분이 있다
  • 처음에는 input width가 좁았었다. 그래서 고민했던 것이…
  • input 넓이보다 안의 내용이 더 길면은 끝부분이 감춰진다

  • input에서 포커스를 해제하면 위 그림처럼,
  • 계속 앞쪽으로 포커스가 자동으로 이동했다

  • 나는 input 내용의 가장 뒤쪽,
  • url param이 변하는 것에 포커스가 가도록 만들려고 이것저것 해봤는데…
  • 결국엔 그냥 input width를 늘려버리고 끝을 냈다…

github pages SPA

  • 깃허브 페이지는 기본적으로 SPA를 지원하지 않는다
  • react-router-dom 으로 여러 경로들을 만들어 두면 index 말고는 404 페이지로 리디렉트 된다
  • 그래서 찾아보니까,,.!
404.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var segmentCount = 1;

var l = window.location;
l.replace(
l.protocol +
'//' +
l.hostname +
(l.port ? ':' + l.port : '') +
l.pathname
.split('/')
.slice(0, 1 + segmentCount)
.join('/') +
'/?p=/' +
l.pathname
.slice(1)
.split('/')
.slice(segmentCount)
.join('/')
.replace(/&/g, '~and~') +
(l.search ? '&q=' + l.search.slice(1).replace(/&/g, '~and~') : '') +
l.hash
);
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(function (l) {
if (l.search) {
var q = {};
l.search
.slice(1)
.split('&')
.forEach(function (v) {
var a = v.split('=');
q[a[0]] = a.slice(1).join('=').replace(/~and~/g, '&');
});
if (q.p !== undefined) {
window.history.replaceState(
null,
null,
l.pathname.slice(0, -1) + (q.p || '') + (q.q ? '?' + q.q : '') + l.hash
);
}
}
})(window.location);
  • 원리는 index 경로 외에 나머지 경로로 들어오면 404페이지를 반환하는데,
  • 커스텀 404페이지에서 스크립트를 통해서 index페이지로 리디렉트 하게 한다
  • 이때, url params 및 query string을 가공한다
  • index.html에서는 404.html로부터 넘겨받은 값으로 라우팅이 적용된 화면을 보여준다
  • 이걸 만든 사람은 정말 대단한 것 같다. ㄷㄷ;

소스코드

참고

github pages spa