React + Unstated-next로 간단한 플젝 만드기
![]()
React + Unstated-next로 간단한 플젝 만드기 🚀
React 프로젝트 초기 설정 🛠
create-react-app 사용
Webpack 설정 vs create-react-app
create-react-app의 webpack
- 참고 : https://medium.com/wasd/create-react-app-%EC%9D%98-webpack-config-js-%EB%93%A4%EC%97%AC%EB%8B%A4%EB%B3%B4%EA%B8%B0-78e40bf37313
react-scripts eject: 숨겨진 설정 파일을 추출하는 명령어config,scripts폴더 나타나고package.json파일에 모든dependency와babel,jest설정 코드가 드러남- cra와 eject 쓰는 이유
- 참고 : https://medium.com/@jsh901220/create-react-app%EC%97%90%EC%84%9C-eject%EC%82%AC%EC%9A%A9%EC%95%88%ED%95%98%EA%B8%B0-customize-cra-react-app-rewired-10a83522ace0
첫 번째 시도
1
npx create-react-app login-poc --typescript
--typescript를 붙였음에도 typescript 설치를 못하고 js로 설치됨
- 두 번째 시도
1
npx create-react-app login-poc --template typescript
cra 공식 깃헙에서도
--template typescript가 공식 타입스크립트 템플릿이라고 함
1
2
3
4
5npx create-react-app my-app --template typescript
# or
yarn create react-app my-app --template typescript
- ❗ 예전에는
--typescript를 붙이면 됐는데--template형식으로 바꼈나보다!
eslint 설정 🛠
eslint 설치
@typescript-eslint/parser 설치 : eslint가 typescript를 lint 할 수 있도록 해줌
@typescript-eslint/eslint-plugin : typescript에 구체화된 eslint rule을 포함한 플러그인 설치
1
yarn add eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --dev
devDependencies에 추가하고 싶으면 뒤에--devoryarn add -D
⁉️ 이슈
tsconfig 의 jsx 부분에서 이슈가 있었는데
Specify JSX code generation: 'preserve', 'react', 'react-jsx', 'react-jsxdev' or'react-native'. Requires TypeScript version 2.2 or later.
VScode의 이슈였당..
This is because VSCode’s Typescript version is not using the newest babel features that create-react-app uses by default.
command + shift + p 에서
typescript: select typescript version에서 useWorkspace version 선택
Prettier 설정 🛠
- 참고: https://flamingotiger.github.io/javascript/eslint-setup/
- prettierrc 설정 후 IDE에서도 설정
- vscode인 경우 settings.json
환경 변수 설정 🛠
참고 : https://create-react-app.dev/docs/adding-custom-environment-variables/
환경변수
참고:
환경변수 : 환경(특정 process)의 조건을 정하는 것
Node.js 기반 :
process.env[key]형태
ex)
process.env.NODE_ENV
크로스 플랫폼 환경변수 설정
create-react-app기반
참고
root 폴더에
.env파일 추가
파일 안에
REACT_APP_변수명으로 변수 생성해서 사용
- 변수명은 무조건
REACT_APP_으로 시작해야 함
- 변수명은 무조건
사용예시
1
2
3<div>
{process.env.REACT_APP_변수명}
</div>
development환경일 때와production환경일 때 다른 api 주소를 가지도록 하려면
- root 폴더에
.env.dev혹은.env.development= 개발 환경.env.prod혹은.env.production= 배포 환경
- 이 외에도
.env.test,.env.local등이 있음
- root 폴더에
package.json의scripts에 따라 불러오는.env파일 결정. 뒤로 갈 수록 우선순위 낮아짐npm start:.env.development.local,.env.development,.env.local,.envnpm run build:.env.production.local,.env.production,env.local,.envnpm test:.env.test.local,.env.test,.env
Unstated-next 설치 🛠
yarn add unstated-next- 튜토리얼 : https://css-tricks.com/managing-state-in-react-using-unstated-next/
Apollo/client 설치 🛠
- ApolloClient를 생성하려면 uri가 필요한데, 고정적인 값이 아닌 환경에 따라 다른 값이 들어가야함
- cra에서 환경변수를 설정하는 방법
- Adding Custom Environment Variables 참고
Axios 설치 🛠
apollo/client를 위해 설정한 환경변수가 root에.env.development이런 식으로 되어있는데,axios의base url은 apollo거랑은 다름- .env.development에 이렇게 환경변수 이름을 다르게 줌
1
2REACT_APP_APOLLO_BASE_URL='https://url주소'
REACT_APP_AXIOS_BASE_URL='https://url 주소'
- .env.development에 이렇게 환경변수 이름을 다르게 줌
- 유연한 axios 인스턴스 만들기
- https://laravel-news.com/building-flexible-axios-clients
- typescript class의 private 변수는?
- https://hyunseob.github.io/2016/10/17/typescript-class/
- 클래스 내부에서만 접근할 수 있으며 내부 인터페이스를 구성할 때 쓰이는 변수
- https://hyunseob.github.io/2016/10/17/typescript-class/
Router 설정 🛠
create-react-app에는 routing을 위한 로직이 없기 때문에react router를 따로 설치해줘야 함routing : 다른 주소에 따라 다른 뷰를 보여주는 것
참고 : https://jeonghwan-kim.github.io/dev/2019/07/08/react-router-ts.html
yarn add react-router-dom
yarn add -D @types/react-router-dom: react-router-dom의 type 정의 라이브러리
<BrowserRouter />: HTML5 히스토리 API를 사용하여 주소를 관리하는 라우터<Switch />: 하위에중 하나를 선택 <Route />: 요청 경로와 렌더링할 컴포넌트를 설정<Redirect />: 요청 경로를 다른 경로롤 리다이렉션
page>index.ts에서Home컴포넌트 lazy 로딩
lazy loading 왜?
React의lazy는 코드분할 을 하도록 해주는데, 코드 분할을 하면 사용자가 필요로 하지 않는 코드를 불러오지 않게 해주어서 앱의 초기 로딩에 필요한 비용을 줄여준다.
참고
React.lazy+Suspense
React.lazy
- 컴포넌트를 렌더링하는 시점에서 비동기적으로 로딩할 수 있게 해주는 util 함수
- 동적 import를 사용해서 컴포넌트를 렌더링
- React 컴포넌트를 포함하며 default export를 가진 모듈로 결정되는 Promise로 반환
- lazy 컴포넌트는 Suspense 컴포넌트 하위에서 렌더링되어야 함.
Suspense
리액트 내장 컴포넌트
코드 분할 된 컴포넌트(lazy 컴포넌트)를 로딩하도록 해주고 로딩이 끝나지 않았을 때 보여줄 UI(예비 컨텐츠)를 설정할 수 있음
1
<Suspense fallback={<div>loading...</div>}
fallbackprops를 통해 로딩 중에 보여 줄 JSX를 지정할 수 있음
⁉️ 이슈
App.tsx에서만들어주고 routes를 map으로 돌리는 과정에서 key 값을 uuid라는 라이브러리를 사용해서 유니크한 값을 사용하려고 했는데 에러 발생
‘uuid’ should be listed in the project’s dependencies. Run ‘npm i -S uuid’ to add it import/no-extraneous-dependencies
- @types/uuid 만 설치해주면 되는 줄 알았는데
uuid도 설치했어야했다. @types는 자바스크립트 라이브러리를 타입스크립트 추론이 가능하도록 도와주는 보조 라이브러리
- @types/uuid 만 설치해주면 되는 줄 알았는데
Unstated-Next 구조 잡기 🛠
참고
최상위인
App.tsx에서container를 내려주는 것이 아니라 해당container가 필요한 컴포넌트에서만 받을 수있도록 컴포넌트를 감싸는 상위 컴포넌트에서Provider로 내려주고container값이 필요한 컴포넌트에서useContainer로 받아와서 상태 값을 사용하도록 만들었다.
Node-sass 설치 🛠
⁉️ 이슈
Error: Node Sass version 5.0.0 is incompatible with ^4.0.0
- https://stackoverflow.com/questions/64625050/error-node-sass-version-5-0-0-is-incompatible-with-4-0-0
CRA uses a fixed version,
yarn add node-sass@4.14.1아직 cra에서 최신 버전의 node-sass를 지원하지 않으니 4.14.1버전으로 설치
etc 📝
Promise.allSettled는 뭐지?- 기존에 구현되어 있던 로그인 기능에
Promise.allSettled라는 메소드가 보여 궁금해졌다.Promise.all만 알고있었는데.. - 참고
Promise.all()- 인자로 받은 Promise 객체들이 하나라도 실패하면 에러로 넘어가고 Promise의 결과들은 무시된다.
Promise.allSettled()- 인자로 iterable 객체(주로 배열)를 받고 객체의 요소들은 모두 Promise 객체
- 성공한 Promise는
{status: 'fulfilled', value: 값}이 반환되고 실패한 Promise는{status: 'rejected', reason: 실패한 이유}를 반환해준다. - 하나라도 실패해도 에러로 넘어가지 않고 모든 Promise들이 실행되어 결과를 받을 수 있다.
- 반환된
status에 따라 처리해줄 수 있음
- 기존에 구현되어 있던 로그인 기능에
no-return-await- 기존에
return await형식으로 사용하는 부분이 많았는데 eslint에서 에러로 던져줬다. - https://eslint.org/docs/rules/no-return-await
- 기존에