diff --git a/.eslintrc.json b/.eslintrc.json index e73fa49..5bdcaab 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,7 +6,11 @@ "shared-node-browser": true, "jest": true }, - "extends": ["eslint:recommended", "plugin:react/recommended"], + "extends": [ + "eslint:recommended", + "plugin:react/recommended", + "plugin:react-hooks/recommended" + ], "parserOptions": { "ecmaFeatures": { "jsx": true diff --git a/package-lock.json b/package-lock.json index 8e31327..b1894cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ "css-loader": "^6.6.0", "eslint": "^8.11.0", "eslint-plugin-react": "^7.29.4", + "eslint-plugin-react-hooks": "^4.6.0", "html-webpack-plugin": "^5.5.0", "prettier": "^2.6.0", "style-loader": "^3.3.1", @@ -4354,6 +4355,18 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -13894,6 +13907,13 @@ } } }, + "eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "requires": {} + }, "eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", diff --git a/package.json b/package.json index a8bb654..65da535 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "css-loader": "^6.6.0", "eslint": "^8.11.0", "eslint-plugin-react": "^7.29.4", + "eslint-plugin-react-hooks": "^4.6.0", "html-webpack-plugin": "^5.5.0", "prettier": "^2.6.0", "style-loader": "^3.3.1", diff --git a/src/components/DragGroup.js b/src/components/DragGroup.js index 3b0f6da..e574695 100644 --- a/src/components/DragGroup.js +++ b/src/components/DragGroup.js @@ -14,28 +14,29 @@ export default function DragGroup({ dispatchGameState, gameState }) { // Capture the pointer. If the pointer could not be captured successfully, end the drag. const dragGroup = React.useRef(null); React.useEffect(() => { + const element = dragGroup.current; let ok = true; try { - dragGroup.current.setPointerCapture(dragState.pointerID); + element.setPointerCapture(dragState.pointerID); } catch (exc) { console.warn("Failed to capture pointer:", exc); ok = false; } - ok &&= dragGroup.current.hasPointerCapture(dragState.pointerID); + ok &&= element.hasPointerCapture(dragState.pointerID); if (!ok) { dispatchGameState({ action: "dragEnd" }); } // Cleanup function to release the pointer. return () => { - if (ok && dragGroup.current) { + if (ok) { try { - dragGroup.current.releasePointerCapture(dragState.pointerID); + element.releasePointerCapture(dragState.pointerID); } catch (exc) { // The pointer is invalid. Normal on touch screens. Ignore it. } } }; - }, [dragState.pointerID]); + }, [dragState.pointerID, dispatchGameState]); // Multi-select timer. React.useEffect(() => { @@ -59,7 +60,7 @@ export default function DragGroup({ dispatchGameState, gameState }) { clearTimeout(timerID); } }; - }, [isShifting, dragState.destination.where, dragState.dragHasMoved]); + }, [isShifting, dragState.destination.where, dragState.dragHasMoved, dispatchGameState]); // Compute location. let top = dragState.pointer.y - dragState.pointerOffset.y;