Reactで変数名エラー|予約語と命名規則を理解する
Reactで発生する変数名エラーの原因と解決方法を解説。JavaScript予約語、命名規則、JSX特有の制約を初心者向けに詳しく説明します。
Reactで変数名エラー|予約語と命名規則を理解する
みなさん、Reactでコードを書いていて、こんな経験はありませんか?
「class
という変数名を使ったらエラーになった...」
「for
を使おうとしたら、なぜか動かない...」
「JSXで属性名を間違えて、思った通りに動かない...」
こんな問題に出会って、困ったことはありませんか?
実は、これらの問題にはちゃんとした理由があるんです。 JavaScriptの予約語やReact特有の命名規則が関係しています。
大丈夫です! この記事を読めば、変数名エラーの原因が分かります。 そして、正しい命名方法も身に付きますよ。
一緒に、エラーのない快適なReact開発を目指しましょう。
JavaScript の予約語とは
基本的な予約語
JavaScriptには**予約語(キーワード)**と呼ばれる、特別な単語があります。 これらの単語は、変数名として使うことができません。
まず、問題のあるコードを見てみましょう。
// エラーになる例(予約語を変数名に使用)
const function = () => { // ❌ 'function' は予約語
console.log('エラー');
};
const class = 'my-class'; // ❌ 'class' は予約語
const for = 'loop'; // ❌ 'for' は予約語
const if = true; // ❌ 'if' は予約語
上のコードを見てください。
エラーが出る理由は、function
、class
、for
、if
がすべて予約語だからです。
JavaScriptが内部で使っている単語なので、変数名には使えないんです。
では、正しい書き方を見てみましょう。
// 正しい書き方
const myFunction = () => { // ✅ 正常
console.log('正常');
};
const className = 'my-class'; // ✅ 正常
const forLoop = 'loop'; // ✅ 正常
const condition = true; // ✅ 正常
このように、予約語を避けて分かりやすい名前を付ければ、エラーは出ません。 少し名前を変えるだけで、すぐに解決できるんです。
主要な予約語一覧
どんな単語が予約語になっているか、一覧で確認してみましょう。
// JavaScript の主要な予約語
const reservedWords = [
// 制御構文
'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'default',
'break', 'continue', 'return',
// 関数・変数宣言
'function', 'var', 'let', 'const',
// オブジェクト・クラス
'class', 'extends', 'super', 'this', 'new',
// モジュール
'import', 'export', 'from', 'as',
// 型・値
'typeof', 'instanceof', 'null', 'undefined', 'true', 'false',
// 例外処理
'try', 'catch', 'finally', 'throw',
// その他
'with', 'debugger', 'delete', 'in', 'of'
];
これらの単語は、すべて変数名として使用できません。
でも、すべて覚える必要はありませんよ。 エラーが出たら「あ、これは予約語だったかな?」と思い出せば大丈夫です。
普段よく使うのは、class
、for
、function
、new
あたりですね。
これらは特に注意しましょう。
React・JSX 特有の制約
JSX属性名の制約
ReactのJSXでは、HTMLと少し違う書き方をする必要があります。
まず、問題のあるJSXコードを見てみましょう。
// 問題のあるJSX(HTML属性をそのまま使用)
const BadComponent = () => {
return (
<div>
<label for="username">ユーザー名</label> {/* ❌ 'for' は予約語 */}
<input class="form-input" /> {/* ❌ 'class' は予約語 */}
<button onclick="handleClick()">クリック</button> {/* ❌ 間違った形式 */}
</div>
);
};
このコードは、HTMLのように書いています。 でも、JSXでは動きません。
なぜかというと、JSXはJavaScriptの中で使うからです。
HTMLのfor
やclass
は、JavaScriptの予約語と衝突してしまうんです。
正しいJSXの書き方を見てみましょう。
// 正しいJSX
const GoodComponent = () => {
const handleClick = () => {
console.log('クリックされました');
};
return (
<div>
<label htmlFor="username">ユーザー名</label> {/* ✅ htmlFor を使用 */}
<input className="form-input" /> {/* ✅ className を使用 */}
<button onClick={handleClick}>クリック</button> {/* ✅ 関数を渡す */}
</div>
);
};
JSXでは、以下のように書き換えます。
for
→htmlFor
class
→className
onclick
→onClick
(キャメルケース)
慣れるまでは忘れやすいですが、エラーメッセージを見れば思い出せますよ。
HTML属性とJSX属性の対応表
よく使う属性の変換表を覚えておきましょう。
// HTML → JSX の変換表
const attributeMapping = {
// よく使われる属性
'class': 'className',
'for': 'htmlFor',
'tabindex': 'tabIndex',
'readonly': 'readOnly',
'maxlength': 'maxLength',
'cellpadding': 'cellPadding',
'cellspacing': 'cellSpacing',
'rowspan': 'rowSpan',
'colspan': 'colSpan',
'usemap': 'useMap',
'frameborder': 'frameBorder',
// データ属性(data-*)
'data-id': 'data-id', // ✅ そのまま使用可能
'data-value': 'data-value', // ✅ そのまま使用可能
// aria属性(aria-*)
'aria-label': 'aria-label', // ✅ そのまま使用可能
'aria-hidden': 'aria-hidden', // ✅ そのまま使用可能
};
基本的なルールは、キャメルケースにすることです。
tabindex
→ tabIndex
のように、単語の境界で大文字にします。
例外的に、data-
やaria-
で始まる属性は、HTMLと同じように書けます。
これらは元々ハイフンが入っているので、そのまま使えるんです。
実際の使用例を見てみましょう。
const AttributeExample = () => {
return (
<div>
<input
className="input-field" // HTML: class
htmlFor="email" // HTML: for
tabIndex={1} // HTML: tabindex
readOnly={false} // HTML: readonly
maxLength={100} // HTML: maxlength
data-testid="email-input" // HTML: data-testid
aria-label="メールアドレス" // HTML: aria-label
/>
</div>
);
};
最初は混乱するかもしれませんが、慣れればとても自然に感じますよ。
よくある変数名エラーと解決法
エラー例1: コンポーネント名の間違い
Reactコンポーネントの名前には、特別なルールがあります。
まず、問題のあるコンポーネント名を見てみましょう。
// 問題のあるコンポーネント名
const userCard = () => { // ❌ 小文字で始まっている
return <div>ユーザーカード</div>;
};
const user_profile = () => { // ❌ アンダースコアが含まれている
return <div>プロフィール</div>;
};
このコンポーネントは、正しく動作しません。 Reactでは、コンポーネント名は必ず大文字で始める必要があるんです。
正しいコンポーネント名を見てみましょう。
// 正しいコンポーネント名
const UserCard = () => { // ✅ PascalCase
return <div>ユーザーカード</div>;
};
const UserProfile = () => { // ✅ PascalCase
return <div>プロフィール</div>;
};
コンポーネント名は、PascalCase(各単語の最初が大文字)で書きます。 これがReactの約束事なんです。
使用する時も、この名前で呼び出します。
const App = () => {
return (
<div>
<UserCard /> {/* ✅ 正常に表示される */}
<UserProfile /> {/* ✅ 正常に表示される */}
</div>
);
};
大文字で始めることで、Reactが「これはコンポーネントだ」と認識してくれます。 小文字で始めると、HTMLタグだと思われてしまうんです。
エラー例2: イベントハンドラの命名
イベントハンドラ(クリック時の処理など)にも、気をつけるポイントがあります。
問題のあるイベントハンドラを見てみましょう。
// 問題のあるイベントハンドラ
const BadEventHandling = () => {
// 予約語を使用
const delete = () => { // ❌ 'delete' は予約語
console.log('削除');
};
// JSXでの間違った書き方
return (
<div>
<button onclick={delete}>削除</button> {/* ❌ onclick は小文字 */}
</div>
);
};
ここには2つの問題があります。
1つ目は、delete
という関数名です。
delete
はJavaScriptの予約語なので、変数名には使えません。
2つ目は、onclick
という属性名です。
JSXでは、onClick
とキャメルケースで書く必要があります。
正しいイベントハンドラを見てみましょう。
// 正しいイベントハンドラ
const GoodEventHandling = () => {
// 適切な関数名
const handleDelete = () => { // ✅ handle + 動作名
console.log('削除');
};
const onRemove = () => { // ✅ on + 動作名
console.log('削除');
};
// JSXでの正しい書き方
return (
<div>
<button onClick={handleDelete}>削除</button> {/* ✅ onClick はキャメルケース */}
<button onClick={onRemove}>削除</button> {/* ✅ 正常 */}
</div>
);
};
イベントハンドラの命名パターンは、主に2つです。
handle
+ 動作名:handleDelete
、handleSubmit
on
+ 動作名:onRemove
、onClick
どちらを使っても大丈夫です。 チーム内で統一していれば問題ありません。
エラー例3: 状態変数の命名
React のuseStateで使う変数名にも、注意点があります。
問題のある状態変数を見てみましょう。
// 問題のある状態変数
const BadStateNaming = () => {
const [new, setNew] = useState(false); // ❌ 'new' は予約語
const [class, setClass] = useState(''); // ❌ 'class' は予約語
const [for, setFor] = useState(''); // ❌ 'for' は予約語
return <div>問題のある状態管理</div>;
};
ここでも、予約語を変数名に使ってしまっています。 これでは、エラーが発生してしまいます。
正しい状態変数の命名を見てみましょう。
// 正しい状態変数
const GoodStateNaming = () => {
const [isNew, setIsNew] = useState(false); // ✅ boolean は is + 形容詞
const [className, setClassName] = useState(''); // ✅ 意味を明確に
const [targetId, setTargetId] = useState(''); // ✅ 具体的な名前
const [user, setUser] = useState(null); // ✅ オブジェクト
const [users, setUsers] = useState([]); // ✅ 配列(複数形)
const [loading, setLoading] = useState(false); // ✅ 状態を表す形容詞
return (
<div className={className}>
{loading ? '読み込み中...' : '完了'}
{isNew && <span>新規</span>}
</div>
);
};
状態変数の命名ポイントは、以下の通りです。
- boolean値には、
is
、has
、can
などを付ける - オブジェクトは単数形で書く
- 配列は複数形で書く
- 状態を表す場合は、形容詞を使う
意味が分かりやすい名前を付けることが、一番大切ですね。
推奨される命名規則
React コンポーネント
Reactコンポーネントの命名ルールをまとめてみましょう。
// コンポーネント名:PascalCase
const UserProfile = () => { /* ... */ };
const ProductCard = () => { /* ... */ };
const NavigationMenu = () => { /* ... */ };
// ファイル名もPascalCaseまたはkebab-case
// UserProfile.jsx または user-profile.jsx
コンポーネント名は、PascalCaseで書きます。 各単語の最初を大文字にするルールですね。
ファイル名は、コンポーネント名と同じにするか、ハイフンつなぎにします。 どちらでも構いませんが、チーム内で統一しましょう。
変数とフック
通常の変数や関数の命名ルールを見てみましょう。
const ExampleComponent = () => {
// 通常の変数:camelCase
const userName = '田中太郎';
const userAge = 25;
const isActive = true;
// 状態変数:camelCase + 意味のある名前
const [currentUser, setCurrentUser] = useState(null);
const [selectedItems, setSelectedItems] = useState([]);
const [isLoading, setIsLoading] = useState(false);
// イベントハンドラ:handle + 動作名 または on + 動作名
const handleLogin = () => { /* ... */ };
const handleSubmit = () => { /* ... */ };
const onClick = () => { /* ... */ };
const onToggle = () => { /* ... */ };
// 定数:SCREAMING_SNAKE_CASE
const API_BASE_URL = 'https://api.example.com';
const MAX_RETRY_COUNT = 3;
return <div>{userName}</div>;
};
変数名の基本は、camelCase(最初は小文字、以降の単語は大文字)です。
状態変数は、何を管理しているか分かりやすい名前を付けましょう。
data
やinfo
みたいな曖昧な名前は避けた方がいいですね。
定数(変わらない値)は、SCREAMING_SNAKE_CASEで書きます。 全部大文字で、単語をアンダースコアでつなぐ書き方です。
boolean 値の命名
真偽値(true/false)の変数には、特別な命名パターンがあります。
const BooleanNamingExample = () => {
// ✅ 推奨:is/has/can/should + 形容詞/動詞
const [isVisible, setIsVisible] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [hasError, setHasError] = useState(false);
const [canEdit, setCanEdit] = useState(true);
const [shouldUpdate, setShouldUpdate] = useState(false);
// ✅ 状態を表す形容詞
const [active, setActive] = useState(false);
const [disabled, setDisabled] = useState(false);
const [loading, setLoading] = useState(false);
return (
<div>
{isVisible && <span>表示中</span>}
{hasError && <span>エラー</span>}
<button disabled={disabled || loading}>
{loading ? '読み込み中...' : 'クリック'}
</button>
</div>
);
};
boolean値の命名パターンは、以下のようなものがあります。
is
+ 形容詞:isVisible
、isActive
has
+ 名詞:hasError
、hasData
can
+ 動詞:canEdit
、canDelete
should
+ 動詞:shouldUpdate
、shouldShow
または、状態を表す形容詞をそのまま使っても構いません。
loading
、active
、disabled
などですね。
逆に避けた方がいい名前もあります。
// ❌ 避けるべき命名
const [flag, setFlag] = useState(false); // 意味が不明
const [check, setCheck] = useState(false); // 曖昧
const [toggle, setToggle] = useState(false); // 動作を表している
flag
やcheck
だと、何を表しているか分かりませんよね。
toggle
は状態ではなく、動作を表す言葉です。
具体的で分かりやすい名前を付けることが大切です。
実践的な例
フォームコンポーネントの例
実際のプロジェクトでよく作る、フォームコンポーネントを見てみましょう。
const UserRegistrationForm = () => {
// 状態変数:具体的で分かりやすい名前
const [formData, setFormData] = useState({
firstName: '', // ✅ 具体的
lastName: '', // ✅ 具体的
emailAddress: '', // ✅ 省略せずに明確
phoneNumber: '', // ✅ 明確
birthDate: '' // ✅ 明確
});
const [validationErrors, setValidationErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [hasSubmitted, setHasSubmitted] = useState(false);
// イベントハンドラ:動作を明確に表現
const handleInputChange = (fieldName) => (event) => {
setFormData(prevData => ({
...prevData,
[fieldName]: event.target.value
}));
};
const handleFormSubmit = async (event) => {
event.preventDefault();
setIsSubmitting(true);
try {
await submitUserRegistration(formData);
setHasSubmitted(true);
} catch (error) {
setValidationErrors({ submit: error.message });
} finally {
setIsSubmitting(false);
}
};
return (
<form onSubmit={handleFormSubmit}>
<div className="form-group">
<label htmlFor="firstName">名前</label>
<input
id="firstName"
type="text"
value={formData.firstName}
onChange={handleInputChange('firstName')}
className={validationErrors.firstName ? 'error' : ''}
disabled={isSubmitting}
/>
{validationErrors.firstName && (
<span className="error-message">
{validationErrors.firstName}
</span>
)}
</div>
<button
type="submit"
disabled={isSubmitting}
className={`submit-button ${isSubmitting ? 'loading' : ''}`}
>
{isSubmitting ? '送信中...' : '登録'}
</button>
{hasSubmitted && (
<div className="success-message">
登録が完了しました
</div>
)}
</form>
);
};
このフォームコンポーネントでは、以下の命名ルールを使っています。
フォームデータ:各フィールドの意味が明確な名前
firstName
、emailAddress
など、省略せずに書いています。
状態管理:何を管理しているか分かりやすい名前
validationErrors
、isSubmitting
、hasSubmitted
イベントハンドラ:動作を明確に表現
handleInputChange
、handleFormSubmit
JSX属性:Reactのルールにしたがってキャメルケース
htmlFor
、onChange
、className
このように、一貫したルールで命名すると、コードがとても読みやすくなります。
データ管理コンポーネントの例
もう少し複雑な例として、商品一覧を管理するコンポーネントを見てみましょう。
const ProductListManager = () => {
// 配列は複数形、オブジェクトは単数形
const [products, setProducts] = useState([]);
const [selectedProduct, setSelectedProduct] = useState(null);
const [filteredProducts, setFilteredProducts] = useState([]);
// 検索・フィルタ関連
const [searchQuery, setSearchQuery] = useState('');
const [categoryFilter, setCategoryFilter] = useState('all');
const [priceRange, setPriceRange] = useState({ min: 0, max: 1000000 });
// UI状態
const [isGridView, setIsGridView] = useState(true);
const [isFilterPanelOpen, setIsFilterPanelOpen] = useState(false);
const [sortOrder, setSortOrder] = useState('name-asc');
// 非同期処理の状態
const [isLoadingProducts, setIsLoadingProducts] = useState(false);
const [hasLoadingError, setHasLoadingError] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
// イベントハンドラ
const handleSearchInputChange = (event) => {
setSearchQuery(event.target.value);
};
const handleCategoryChange = (category) => {
setCategoryFilter(category);
};
const handleProductSelect = (productId) => {
const product = products.find(p => p.id === productId);
setSelectedProduct(product);
};
const handleViewModeToggle = () => {
setIsGridView(previousValue => !previousValue);
};
const handleSortOrderChange = (newSortOrder) => {
setSortOrder(newSortOrder);
};
return (
<div className="product-list-manager">
{/* 検索・フィルタ UI */}
{/* 商品一覧 UI */}
{/* 詳細表示 UI */}
</div>
);
};
この例では、以下の命名パターンを使っています。
データの種類別:
- 配列:
products
、filteredProducts
(複数形) - オブジェクト:
selectedProduct
、priceRange
(単数形)
機能別:
- 検索関連:
searchQuery
、categoryFilter
- UI状態:
isGridView
、isFilterPanelOpen
- 非同期処理:
isLoadingProducts
、hasLoadingError
イベントハンドラ:
handle
+ 対象 + 動作:handleSearchInputChange
handle
+ 動作:handleProductSelect
このように整理すると、どの変数が何を管理しているか、一目で分かりますね。
デバッグとエラー対処
よくあるエラーメッセージと対処法
実際の開発でよく遭遇するエラーと、その解決方法を見てみましょう。
// エラー1: Unexpected token
// 原因:予約語を変数名に使用
const function = () => { }; // ❌
// 対処法:別の名前を使用
const customFunction = () => { }; // ✅
Unexpected token
エラーが出た時は、予約語を使っていないか確認してください。
エラーメッセージの行番号を見れば、どこが問題か分かります。
// エラー2: Cannot read property 'map' of undefined
// 原因:配列でない値にmapを使用
const items = null;
return items.map(item => <div key={item.id}>{item.name}</div>); // ❌
// 対処法:配列であることを確認
const items = [];
return items?.map(item => <div key={item.id}>{item.name}</div>); // ✅
このエラーは、items
がnull
やundefined
の時に発生します。
items?.map
のように、オプショナルチェーンを使うと安全です。
// エラー3: Warning: Invalid DOM property
// 原因:HTML属性をそのまま使用
<div class="container" for="input"> // ❌
// 対処法:JSX用の属性名を使用
<div className="container" htmlFor="input"> // ✅
このワーニングは、JSX用の属性名を使わなかった時に出ます。
class
→ className
、for
→ htmlFor
に変更しましょう。
これらのエラーは、慣れれば簡単に解決できるようになります。 エラーメッセージをよく読んで、落ち着いて対処していきましょう。
まとめ
React で変数名エラーを避けるために覚えておくポイントをまとめますね。
重要なルール
JavaScript 予約語を変数名に使わない
class
、for
、function
、new
などは避けましょう。
JSX 属性名を正しく使う
className
、htmlFor
、onClick
など、キャメルケースで書きます。
コンポーネント名は PascalCase
UserCard
、ProductList
のように、各単語の最初を大文字にします。
変数・関数名は camelCase
userName
、handleClick
のように、最初は小文字で書きます。
boolean 値には適切な接頭詞を使う
isVisible
、hasError
、canEdit
など、意味が分かりやすい名前にします。
配列は複数形、オブジェクトは単数形
users
(配列)、user
(オブジェクト)のように使い分けます。
命名の基本原則
意味が明確で理解しやすい名前を付ける
data
やinfo
より、userProfile
やproductList
の方が分かりやすいです。
一貫した命名規則を守る チーム内で同じルールを使うことが大切です。
省略よりも明確性を重視する
usr
よりuser
、btn
よりbutton
の方が読みやすいです。
チーム内でのルールを統一する みんなで同じスタイルを使えば、コードの品質が向上します。
最後に
適切な命名規則を守ることで、読みやすく保守しやすいReactアプリケーションを作れます。
最初は覚えることが多く感じるかもしれません。 でも大丈夫です。
エラーが出たら、この記事を思い出してください。 少しずつ慣れていけば、自然に正しい名前を付けられるようになりますよ。
何より大切なのは、他の人が読んでも分かりやすいコードを書くことです。 将来の自分も含めて、みんなが理解しやすいコードを目指しましょう。
ぜひ実際のプロジェクトで、これらのルールを試してみてくださいね。