写経・整理 | りあクト! TypeScriptで始めるつらくないReact開発 第3.1版【Ⅱ. React基礎編】
Yarn
npmよりも後にFacebook、Google、Exponent、Tildeによって開発されたJavaScriptのパッケージマネージャー。
インストール
$ npm install yarn
ESLint
Find and fix problems in your JavaScript code
https://eslint.org/docs/user-guide/getting-started
$ yarn eslint --init
? How would you like to use ESLint? …
✓ To check syntax, find problems, and enforce code style
? What type of modules does your project use? …
✓ JavaScript modules (import/export)
? 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?
✓ Use a popular style guilde
? Which style guide do you want to follow?
✓ Airbnb: https://github.com/airbnb/javascript
? What format do you want your config file to be in?
✓ JavaScript
? Would you like to install them now with npm?
✓ No
出力された .eslintrc.js
module.exports = {
"env": {
"browser": true,
"es2021": true
},
"extends": [
"plugin:react/recommended",
"airbnb"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"react",
"@typescript-eslint"
],
"rules": {
}
};
$ yarn add -D eslint-plugin-react @typescript-eslint/eslint-plugin \
eslint-config-airbnb eslint-plugin-import eslint-plugin-jsx-a11y \
eslint-plugin-react-hooks @typescript-eslint/parser
yarn add <package...> -D
-D|--dev
オプションを指定することで、devDependenciesにパッケージ追加する
$ typesync
Install missing TypeScript typings for dependencies in your package.json.
package.jsonに含まれる依存関係で欠けているTypeScrptの型定義ファイルをインストールする
$ yarn typesync
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'plugin:react/recommended',
'airbnb',
'airbnb/hooks',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 12,
project: './tsconfig.eslint.json',
sourceType: 'module',
tsconfigRootDir: __dirname,
},
plugins: [
'@typescript-eslint',
'import',
'jsx-a11y',
'react',
'react-hooks',
],
root: true,
rules: {
// occur error in `import React from 'react'` with react-scripts 4.0.1
'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': [
'error',
],
'lines-between-class-members': [
'error',
'always',
{
exceptAfterSingleLine: true,
},
],
'no-void': [
'error',
{
allowAsStatement: true,
},
],
'padding-line-between-statements': [
'error',
{
blankLine: 'always',
prev: '*',
next: 'return',
},
],
'@typescript-eslint/no-unused-vars': [
'error',
{
'vars': 'all',
'args': 'after-used',
'argsIgnorePattern': '_',
'ignoreRestSiblings': false,
'varsIgnorePattern': '_',
},
],
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
},
],
'react/jsx-filename-extension': [
'error',
{
extensions: ['.jsx', '.tsx'],
},
],
'react/jsx-props-no-spreading': [
'error',
{
html: 'enforce',
custom: 'enforce',
explicitSpread: 'ignore',
},
],
'react/react-in-jsx-scope': 'off',
},
overrides: [
{
'files': ['*.tsx'],
'rules': {
'react/prop-types': 'off',
},
},
],
settings: {
'import/resolver': {
node: {
paths: ['src'],
},
},
},
};
extends
に記述するのは各プラグインの推奨の共有設定で、記述される順番には意味があるため注意。
共有設定間で設定ルールの値が衝突したら、後に記述したものが先に記述されたものを上書きする(後勝ち)
plugins
には読み込ませる追加のプラグインを記述する。
yarn add
して依存関係に追加するだけでは有効にならず、設定ファイルにプラグイン名を記述する必要がある。
rules
には各ルールの適用の可否やエラーレベルを設定する。
.eslintignore
ファイルはESLintのチェックの対象外となるファイルを定義する。
[.eslintignore]
build/
public/
**/coverage/
**/node_modules/
**/*.min.js
*.config.js
.*lintrc.js
Prettier
ESLint の環境に Prettier を加えるのに必要なパッケージは2つ
- prettier
- Prettier 本体
- eslint-config-prettier
- Prettier と強豪する可能性のある ESLint の各種ルールを無効にする共有設定
$ yarn add -D prettier eslint-config-prettier
$ yarn typesync
$ yarn
.eslintrc.js
の設定項目である extends
に prettier
を追加する。
.prettierrc
という名前でプロジェクトルートにファイルを作成する。
[.prettierrc]
singleQuote: true
trailingComma: "all"
create-react-appで生成したデフォルトのコードに対してESLintを実行すると src/reportWebVitals.ts
でエラーが検知された。
エラー内容は以下の通り。
3:25 warning Missing return type on function @typescript-eslint/explicit-module-boundary-types
5:5 error Promises must be handled appropriately or explicitly marked as ignored with the `void` operator @typescript-eslint/no-floating-promises
warningはひとまず置いておいて、errorである @typescript-eslint/no-floating-promises
の方を解消する。
[before]
import { ReportHandler } from 'web-vitals';
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;
「import('web-vitals').then(...)
の返り値の型がないから何か適切な処理をするか、 void
を指定しなさい」と怒られているので、とりあえず void
を指定するとエラーを解消することができた。
あと、warningの方は3行目の関数の返り値の型がないから指定しておいてねと言われているので指定すると解消できた。
修正後は以下の通り。
[after]
import { ReportHandler } from 'web-vitals';
const reportWebVitals: ReportHandler | undefined = (
onPerfEntry?: ReportHandler,
) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
void import('web-vitals').then(
({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
},
);
}
};
export default reportWebVitals;
フロントエンジニアをされている方々は、ESLintとかサクッと設定しちゃうんだろうか?
慣れてないのもあるけど、他の言語のLint設定より難しく感じる。。。
2019年2月リリースのバージョン 16.8.0
からは、関数コンポーネント(Function Component)で記述することが推奨されるようになった。
Reactの関数コンポーネントの型インターフェースには FunctionComponent
が用意されている。
VFC
とエイリアスされている VoidFunctionComponent
インターフェースもある。
従来の
FC
で定義された関数コンポーネントでは、子要素の操作が必要ない場合でも暗黙のうちに propsの中に子要素のオブジェクトが渡されていた。
この VoidFunctionComponent
は子要素をいじらない関数コンポーネントの型定義に使うことが推奨されている。