[TS] React with TypeScript
- react-typescript-template @ pjchender github
- React and TypeScript @ front-end master
- React TypeScript CheatSheet
- typescript-cheatSheets/react @ GitHub
專案設置
建立專案
- 透過 create-react-app 產生專案
$ npx create-react-app my-app --template typescript
// 如果希望支援 React v17 不需要再寫 import React 的這個 feature
{
"jsx": "react-jsx" // 需要使用 "react-jsx" 而不能是 "react"
}
- 定義 eslintrc.js
$ npx eslint --init
# 安裝完 eslint 後可能會與 create-react-app 的 ESLint 有版本衝突
# 先移除 package.json 中的 eslint
$ rm package-lock.json
$ rm -rf node_modules
$ npm install
- 定義 .prettierrc
- 若要整合到 ESLint 需留意和 TypeScript 可能的衝突,可參考這篇的設定。
ESLint 設定
參考設定:create-exposed-app:eslint-config-airbnb-typescript 的參考設定。
React Error : is declared but its value is never read
:參考 Introducing the New JSX Transform,升級到 react v17 後,不需要import React
的 ESLint 設定
@typescript-eslint/eslint-plugin
- Getting Started - Linting your TypeScript Codebase:說明整個安裝設定流程 @ Github
- Getting Started - Linting with Type Information:讓 Lint 可以顯示型別的訊息 @ Github
錯誤處理:Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser
出現錯誤訊息:
Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: .eslintrc.js.
The file must be included in at least one of the projects provided
這個錯誤的意思是該檔案(.eslintrc.js
)並沒有被包含在 tsconfig 的設定(include
)中。之所以會有這個錯誤是因為 @typescript-eslint/parser
會試著去解析這隻檔案。
根據要不要實際讓 ESLint 去解析這支檔案的需求不同會有不同的設定方式,可以參考下方的文件。
- 最簡單的解決方式是把
.eslintrc.js
放到.eslintignore
中,這樣 ESLint 就不會去解析.eslintrc.js
這支檔案。 - 如果需要 lint 這隻檔案,但不需要出現 type-aware linting,則可以使用 ESLint 提供的 overrides 設定(可參考這裡)
參考
- I get errors telling me "The file must be included in at least one of the projects provided" @ typescript-eslint Github
- TypeScript ESLint @ Official Github
- Learn TypeScript Linting Part 1 @ Mountain Top
eslint-config-airbnb-typescript
eslint-config-airbnb-typescript:安裝與設定方式 @ Github
eslint-plugin-eslint-comments
針對的是 ESLint 在檔案中提供的指令,例如 /* eslint-disable */
。
eslint prettier
eslint-plugin-prettier 可以透過 ESLint 的規則來達到 prettier 的效果,為了要讓此 plugin 正確運作,最好可以把和 code formatting 有關的 ESLint 規則都關閉,只使用 ESLint 來確保程式碼品質、並偵測出可能的問題。要把和 code formatting 有關的 ESLint 規則都關閉,則可以使用 eslint-config-prettier 這個工具。
eslint-config-prettier
: used for disable all formatting-related ESLint rules.eslint-plugin-prettier
:透過 ESLint 來達到 prettier 的效果
Prettier 的原則是,透過 Prettier 來編排程式碼(code formatting);透過 linter(例如,ESLint)來確保程式碼的品質(code-quality)及避免可能的 bug。
安裝:
npm install --save-dev eslint prettier eslint-plugin-prettier eslint-config-prettier
使用:
// .eslintrc.js
{
// 這會套用 eslint-config-prettier 設定好的規則
extends: ['plugin:prettier/recommended'] // 放在陣列中最後一個
}
在根目錄建立 .prettierrc
後,eslint-config-prettier 則預設就會去讀取這支檔案。
在 extends
中使用 plugin:prettier/recommend
後,即可省略下述設定:
// 使用 plugin:prettier/recommend 的話,即可省略下述設定
{
"extends": ["prettier"],
"plugins": ["prettier"],
"rules": {
"prettier/prettier": "error", // 預設就會讀 .prettierrc
"arrow-body-style": "off",
"prefer-arrow-callback": "off"
}
}
參考
- eslint-config-prettier:將和 Prettier 無關或可能導致衝突的規則關閉 @ github
- eslint-plugin-prettier:透過 ESLint 的規則來達到 prettier 的效果@ github
- Integrating with Linters @ Prettier Docs
Lint Staged
- from lint-staged v10,
git add
part is automatic and not necessary to include in configuration. Some of your tasks use git add command.(#775)
React Props with Type
Basic
interface Props {
text: string;
}
const Banner = ({ text }: Props) => {
return <h1>Hello, {text}</h1>;
};
children as Props
keywords: React.ReactNode
一般 children 建議使用 React.ReactNode
,參考 react-typescript-cheatsheet:
type BannerProps = { children: React.ReactNode };
const Banner = ({ children }: BannerProps) => {
return <h1>{children}</h1>;
};
CSS style as Props
keywords: React.CSSProperties
type BannerProps = { style?: React.CSSProperties };
const Banner = ({ style = {} }: BannerProps) => {
return <h1 style={style}>Hello React with TypeScript</h1>;
};
Banner.defaultProps = {
style: {},
};
事件
針對 React 元件上的 DOM 事件,可以利用 VSCode 提供的 hint,只需將滑鼠移到事件上方即可。
例如,將滑鼠移到 onSubmit
,就可以知道這裡面取得的 event 其型別會是 React.FormEvent<HTMLFormElement>
:
同樣的,將滑鼠移到 onChange
事件上,就可以知道這個事件的 event
其型別會是 React.ChangeEvent<HTMLInputElement>
:
或者,在該事件中先帶入一個空的 ()
,再透過 parameter hint 即可看到提示:
知道 event 的型別後就可以撰該 event 的 handle function:
interface Props {
onClick(event: React.MouseEvent<HTMLButtonElement>): void;
}
React Hooks with Type
useState
// useState<StateType>();
const [isOpen, setIsOpen] = useState<boolean>(false);
const [data, setData] = useState<DateType | null>(null);
React Class Component With Type
import { ChangeEvent, Component } from 'react';
type CounterProps = {
incident: string;
};
type CounterState = {
count: number;
};
class Counter extends Component<CounterProps, CounterState> {
constructor(props: CounterProps) {
super(props);
this.state = {
count: 0,
};
}
// ...
render() {
const { incident } = this.props;
const { count } = this.state;
return (
/* ... */
);
}
}
export default Counter;