diff --git a/assets/eslint.config.mjs b/assets/eslint.config.mjs index a14e5d785..6594fb47d 100644 --- a/assets/eslint.config.mjs +++ b/assets/eslint.config.mjs @@ -2,6 +2,7 @@ import globals from "globals"; import pluginJs from "@eslint/js"; import tseslint from "typescript-eslint"; import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; +import pluginReactHooks from "eslint-plugin-react-hooks"; import eslintConfigPrettier from "eslint-config-prettier"; import jestPlugin from "eslint-plugin-jest"; @@ -15,6 +16,16 @@ export default [ files: ["test/**"], ...jestPlugin.configs["flat/style"], }, + { + files: ["**/*.{ts, tsx}"], + plugins: { + "react-hooks": pluginReactHooks, + }, + rules: { + ...pluginReactHooks.configs.recommended.rules, + "react-hooks/exhaustive-deps": "error", + }, + }, { settings: { react: { version: "detect" } }, rules: { diff --git a/assets/package-lock.json b/assets/package-lock.json index e86228489..15ff9d15e 100644 --- a/assets/package-lock.json +++ b/assets/package-lock.json @@ -49,6 +49,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.5.0", "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-hooks": "^4.6.2", "exit_on_eof": "^1.0.4", "file-loader": "^6.2.0", "fishery": "^2.2.2", @@ -7397,6 +7398,18 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "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", "dev": true, diff --git a/assets/package.json b/assets/package.json index 71949ecec..26fd09a9b 100644 --- a/assets/package.json +++ b/assets/package.json @@ -61,6 +61,7 @@ "eslint-config-prettier": "^9.1.0", "eslint-plugin-jest": "^28.5.0", "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-hooks": "^4.6.2", "exit_on_eof": "^1.0.4", "file-loader": "^6.2.0", "fishery": "^2.2.2", diff --git a/assets/src/hooks/v2/use_refresh_rate.ts b/assets/src/hooks/v2/use_refresh_rate.ts index 468829ff6..0f2631b12 100644 --- a/assets/src/hooks/v2/use_refresh_rate.ts +++ b/assets/src/hooks/v2/use_refresh_rate.ts @@ -11,27 +11,28 @@ interface RefreshRateConfig { const useRefreshRate = (): RefreshRateConfig => { const screenId = useScreenID(); - // Live OFM screens ignore any configured refreshRate. - // Hardcoding to 0 prevents an interval from being started unnecessarily. - const refreshRate = isOFM() ? "0" : fetchDatasetValue("refreshRate"); - const refreshRateOffset = getDatasetValue("refreshRateOffset") || "0"; - const screenIdsWithOffsetMap = getDatasetValue("screenIdsWithOffsetMap"); - const refreshRateMs = parseFloat(refreshRate) * 1000; + return useMemo(() => { + // Live OFM screens ignore any configured refreshRate. + // Hardcoding to 0 prevents an interval from being started unnecessarily. + const refreshRate = isOFM() ? "0" : fetchDatasetValue("refreshRate"); + const refreshRateOffset = getDatasetValue("refreshRateOffset") || "0"; + const screenIdsWithOffsetMap = getDatasetValue("screenIdsWithOffsetMap"); + + const refreshRateMs = parseFloat(refreshRate) * 1000; + + let refreshRateOffsetMs; - const refreshRateOffsetMs = useMemo(() => { if (screenIdsWithOffsetMap) { const screens = JSON.parse(screenIdsWithOffsetMap); - return _.find(screens, { id: screenId }).refresh_rate_offset * 1000; + refreshRateOffsetMs = + _.find(screens, { id: screenId }).refresh_rate_offset * 1000; + } else { + refreshRateOffsetMs = parseFloat(refreshRateOffset) * 1000; } - return parseFloat(refreshRateOffset) * 1000; - }, []); - - return { - refreshRateMs, - refreshRateOffsetMs, - }; + return { refreshRateMs, refreshRateOffsetMs }; + }, [screenId]); }; export default useRefreshRate;