はじめに
Reactの学習はじめたけど、JSXもよくわからんな〜って方が対象です。
私自身、見切り発車で学習を進め、いよいよCustom Hookというときに少しだけエラーでハマったのでメモ。
この記事でわかること
-
'React' is defined but never used. eslint@typescript-eslint/no-unused-vars)
の対策と意味
構築環境
- react: 17.0.1
- typescript: 4.0.3
- eslint: 7.12.1
- @typescript-eslint/eslint-plugin: 4.6.1
- @typescript-eslint/parser: 4.6.1
先に結論だけ
ざっくり言うと、
JSX表記が無いときはimport React from 'react';
する必要がないということです。
React
をimport
しないようにすれば、ESLintに怒られなくなります。
以上です。
これで理解できた方は、この記事を読む必要はもうありません!
ちょっと解説
Reactの勉強をしてると、つい思考停止でファイルの一行目からimport React from 'react';
してませんか?
わたしです。
さて、今回の経緯を説明します。
1. 何が起こったか
React Hooksの勉強として、Hooksを使ってシンプルなカウントダウンタイマーアプリを作成しました。
そのあとHooksのロジック部分を、Custom Hookを使って新しいファイルに分離、作成したところでエラーが出ました。
ディレクトリ構成は以下のようなものを想定してください。
src/
├hooks/
└use-timer.tsx
├App.tsx
├Timer.tsx
Timer.tsx
のHooks部分を、use-timer.tsx
に分離する感じです。
そして、エラーが起こった状態のuse-timer.tsx
の中身を見てみます。
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
// 'React' is defined but never used. eslint@typescript-eslint/no-unused-vars
export const useTimer = (limit: number): [number, boolean, () => void] => {
const [timeLeft, setTimeLeft] = useState(limit);
const primes = useMemo(() => getPrimes(limit), [limit]);
const reset = useCallback(() => setTimeLeft(limit), [limit]);
const tick = () => setTimeLeft((t) => t - 1);
const timerId = useRef<NodeJS.Timeout>();
useEffect(() => {
// 省略
}, []);
return [timeLeft, primes.includes(timeLeft), reset];
};
たくさんHooksの処理がありますが、useTimer
にまとめられています。それがCustom Hookです。
難しそうだけど便利だな〜と思っていたら、一行目でエラーが!
'React' is defined but never used. eslint@typescript-eslint/no-unused-vars)
え、こんだけReact Hooks使ってるファイルでReact
使われてないわけないだろw
結果、使われていませんでした。
2. エラーの意味と対策
少し方向は違いますが、ぐぐったらこんな質問がありました。
I saw the examples where https://reactjs.org/docs/hooks-custom.html they always do:
import React, { useState, useEffect } from 'react';
But React is not really used in the file, do we really need it and why?
訳)
「公式ドキュメントのCutom Hookの例ではimport React
してるけど、それって実際は使われてないですよね、ほんとうに必要なんですか?」
答え:
You will need React if you are rendering JSX.
訳)
「JSXをレンダリングするならReactは必要ですよ」
つまり、React
ライブラリをimport
する必要があるのは、JSXを記述しているときなのでした。
私の場合は、ESLintが、JSXもないのにReact
は必要ないですよ、と教えてくれていたのです。
もう一度use-timer.tsx
の中身をよく見てみると、JSXはありません。
さあ、React
を消しましょう。
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
めでたしめでたし。
3. 補足:JSXとは?
冗長かもしれませんが、ちょっとそれだけだと意味がよくわかんないって方へ。
落ち着いて、JSXの正体を確認しましょう。
たとえば、Click!
と書かれたsubmit
属性のbutton
要素を生成するコードを示します。
以下の2つは同じ意味です。
JSXの記法だと、
<Button type="submit">
Click!
</Button>
これがJavaScriptにコンパイルされると、
React.createElement(
'button',
{ type: 'submit' },
'Click!'
);
なんと実は、JSXは、React.createElement
というメソッドコールをすることで、オブジェクト生成していたのです。
これまでimport React
していたのは、JSXを使用するためだった!(何度でも言う)
まとめ
- ReactとJSXの魔法に惑わされるな!
- エラーメッセージがすべて教えてくれる
- Qiita初投稿で記事書くの難しかったけど楽しい!
間違ってたら修正します。