Reactで「confirm」エラーを回避! 代替手段とカスタムダイアログでスマートな開発
React.jsにおける「予期せぬ 'confirm' の使用」エラー:詳細解説
React.jsアプリケーションで、confirm
関数を使用すると、no-restricted-globals
ルールによって「予期せぬ 'confirm' の使用」というエラーが発生することがあります。これは、eslint
などの静的コード解析ツールが、グローバル変数の confirm
の使用を制限しているためです。
エラーの原因
confirm
関数は、ブラウザのポップアップウィンドウを表示して、ユーザーに確認を求めるために使用されます。しかし、この関数はユーザー体験を妨害したり、予期しない動作を引き起こしたりする可能性があるため、多くの場合、Reactアプリケーションでは好ましくありません。
解決策
このエラーを解決するには、以下の2つの方法があります。
window.confirm を使用する
confirm
関数はグローバル変数なので、window.confirm
のように明示的にプレフィックスを付けることで使用できます。
// eslint-disable-next-line no-restricted-globals
if (window.confirm("この操作を実行しますか?")) {
// ...
}
代替手段を使用する
confirm
関数の代わりに、以下の代替手段を使用することができます。
useReducer
フックを使用して、独自のステート管理ロジックを実装するreact-bootstrap
などのライブラリからモーダルコンポーネントを使用する- カスタムダイアログコンポーネントを作成する
予防策
- コードレビューを通じて、
confirm
関数の不要な使用を検出する eslint-plugin-react
などのプラグインを使用して、Reactアプリケーションに特化したルールを適用する.eslintrc
ファイルにno-restricted-globals
ルールの例外を追加する
- 代替手段を使用することで、より良いユーザー体験とコードの保守性を確保することができます。
confirm
関数は、ユーザーとの対話を必要とする場合にのみ使用することをお勧めします。no-restricted-globals
ルールは、プロジェクトのコーディング規範に合わせて設定する必要があります。
function deleteItem(id) {
if (confirm("このアイテムを削除しますか?")) {
// 削除処理
}
}
以下の2つの方法でエラーを解決できます。
function deleteItem(id) {
if (window.confirm("このアイテムを削除しますか?")) {
// 削除処理
}
}
import React, { useState } from 'react';
function DeleteDialog({ id, onConfirm }) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleConfirm = () => {
onConfirm(id);
setShow(false);
};
return (
<>
<button onClick={() => setShow(true)}>削除</button>
{show && (
<div className="dialog">
<p>このアイテムを削除しますか?</p>
<button onClick={handleClose}>キャンセル</button>
<button onClick={handleConfirm}>削除</button>
</div>
)}
</>
);
}
function App() {
const [items, setItems] = useState([1, 2, 3]);
const handleDelete = (id) => {
setItems(items.filter((item) => item !== id));
};
return (
<>
{items.map((item) => (
<div key={item}>
<p>{item}</p>
<DeleteDialog id={item} onConfirm={handleDelete} />
</div>
))}
</>
);
}
説明
handleDelete
関数は、削除するアイテムのIDを受け取り、items
ステートからそのアイテムを削除します。
App
コンポーネントは、items
ステートを使用してアイテムリストをレンダリングします。各アイテムには、DeleteDialog
コンポーネントが埋め込まれています。このコンポーネントは、handleDelete
関数にアイテムのIDを渡して、削除処理を実行します。
利点
- テストが容易になります。
- コードのモジュール化と再利用性を向上させることができます。
- カスタムダイアログコンポーネントを使用することで、ユーザー体験をより洗練させることができます。
react-bootstrap の Modal コンポーネントを使用する
react-bootstrap
は、ReactアプリケーションでBootstrapコンポーネントを使用するためのライブラリです。このライブラリには、モーダルダイアログを表示するための Modal
コンポーネントが含まれています。
import React, { useState } from 'react';
import Modal from 'react-bootstrap/Modal';
function DeleteDialog({ id, onConfirm }) {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleConfirm = () => {
onConfirm(id);
setShow(false);
};
return (
<>
<Button onClick={() => setShow(true)}>削除</Button>
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>アイテム削除</Modal.Title>
</Modal.Header>
<Modal.Body>このアイテムを削除しますか?</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
キャンセル
</Button>
<Button variant="primary" onClick={handleConfirm}>
削除
</Button>
</Modal.Footer>
</Modal>
</>
);
}
// ... (Appコンポーネントは前回と同じ)
useReducer
フックを使用して、独自のステート管理ロジックを実装することで、confirm
関数を使用せずに削除確認ダイアログを制御できます。
import React, { useState, useReducer } from 'react';
const initialState = {
showDeleteDialog: false,
itemId: null,
};
const reducer = (state, action) => {
switch (action.type) {
case 'SHOW_DELETE_DIALOG':
return {
...state,
showDeleteDialog: true,
itemId: action.payload,
};
case 'HIDE_DELETE_DIALOG':
return {
...state,
showDeleteDialog: false,
itemId: null,
};
case 'CONFIRM_DELETE':
// 削除処理
return {
...state,
showDeleteDialog: false,
itemId: null,
};
default:
return state;
}
};
function DeleteDialog({ onConfirm }) {
const [dispatch] = useReducer(reducer, initialState);
const { showDeleteDialog, itemId } = useReducer(reducer, initialState);
const handleClose = () => dispatch({ type: 'HIDE_DELETE_DIALOG' });
const handleConfirm = () => {
onConfirm(itemId);
dispatch({ type: 'CONFIRM_DELETE' });
};
return (
<>
{showDeleteDialog && itemId && (
<div className="dialog">
<p>このアイテムを削除しますか?</p>
<button onClick={handleClose}>キャンセル</button>
<button onClick={handleConfirm}>削除</button>
</div>
)}
</>
);
}
function App() {
const [items, setItems] = useState([1, 2, 3]);
const [dispatch] = useReducer(reducer, initialState);
const handleDelete = (id) => {
dispatch({ type: 'SHOW_DELETE_DIALOG', payload: id });
};
return (
<>
{items.map((item) => (
<div key={item}>
<p>{item}</p>
<button onClick={() => handleDelete(item)}>削除</button>
</div>
))}
<DeleteDialog onConfirm={handleDelete} />
</>
);
}
- アプリケーションのステート管理をより詳細に制御できます。
- 使用するライブラリやフレームワークによって、`confirm
reactjs