From 1a5b014a7ac072d3937e9439f6d038f88c9af838 Mon Sep 17 00:00:00 2001
From: Jan Potoms <2109932+Janpot@users.noreply.github.com>
Date: Fri, 20 Sep 2024 18:27:09 +0200
Subject: [PATCH] [code-infra] Enable React compiler eslint plugin (#4121)
Co-authored-by: Pedro Ferreira <10789765+apedroferreira@users.noreply.github.com>
---
.eslintrc.js | 14 ++++----
docs/pages/toolpad/studio/index.js | 4 +--
.../src/DashboardLayout/DashboardLayout.tsx | 8 +++--
.../NotificationsProvider.tsx | 10 ++++--
.../toolpad-studio/src/utils/useThottled.ts | 34 -------------------
packages/toolpad-utils/src/hooks/useLatest.ts | 12 +++----
6 files changed, 25 insertions(+), 57 deletions(-)
delete mode 100644 packages/toolpad-studio/src/utils/useThottled.ts
diff --git a/.eslintrc.js b/.eslintrc.js
index 5b5b1650cd0..795d73fa5aa 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -2,8 +2,6 @@ const baseline = require('@mui/monorepo/.eslintrc');
const path = require('path');
const lodash = require('lodash');
-const ENABLE_REACT_COMPILER_PLUGIN = false;
-
const ALLOWED_LODASH_METHODS = new Set(['throttle', 'debounce', 'set']);
const noRestrictedImports = {
@@ -33,11 +31,7 @@ const noRestrictedImports = {
module.exports = {
...baseline,
- plugins: [
- ...baseline.plugins,
- ...(ENABLE_REACT_COMPILER_PLUGIN ? ['eslint-plugin-react-compiler'] : []),
- 'testing-library',
- ],
+ plugins: [...baseline.plugins, 'eslint-plugin-react-compiler', 'testing-library'],
settings: {
'import/resolver': {
webpack: {
@@ -101,7 +95,7 @@ module.exports = {
},
],
'material-ui/no-hardcoded-labels': 'off', // We are not really translating the docs/website anymore
- ...(ENABLE_REACT_COMPILER_PLUGIN ? { 'react-compiler/react-compiler': 'error' } : {}),
+ 'react-compiler/react-compiler': 'error',
},
overrides: [
...baseline.overrides,
@@ -197,5 +191,9 @@ module.exports = {
'no-restricted-imports': ['error', noRestrictedImports],
},
},
+ {
+ files: ['packages/toolpad-studio/src/**/*'],
+ rules: { 'react-compiler/react-compiler': 'off' },
+ },
],
};
diff --git a/docs/pages/toolpad/studio/index.js b/docs/pages/toolpad/studio/index.js
index b64e7ec6f55..86df5b4068e 100644
--- a/docs/pages/toolpad/studio/index.js
+++ b/docs/pages/toolpad/studio/index.js
@@ -15,7 +15,7 @@ import CardGrid from '../../../src/components/landing-studio/CardGrid';
import Pricing from '../../../src/components/landing-studio/PricingTable';
import Marquee from '../../../src/components/landing-studio/Marquee';
import features from '../../../data/toolpad/studio/landing/features';
-import useCases from '../../../data/toolpad/studio/landing/useCases';
+import studioUseCases from '../../../data/toolpad/studio/landing/useCases';
import marquee from '../../../data/toolpad/studio/landing/marquee';
import {
Headline,
@@ -44,7 +44,7 @@ export default function Home() {
-
+
diff --git a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
index 393d6ea66ad..b21df1beee3 100644
--- a/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
+++ b/packages/toolpad-core/src/DashboardLayout/DashboardLayout.tsx
@@ -416,7 +416,6 @@ function DashboardLayout(props: DashboardLayoutProps) {
const [isNavigationFullyExpanded, setIsNavigationFullyExpanded] =
React.useState(isNavigationExpanded);
- // eslint-disable-next-line consistent-return
React.useEffect(() => {
if (isNavigationExpanded) {
const drawerWidthTransitionTimeout = setTimeout(() => {
@@ -427,6 +426,8 @@ function DashboardLayout(props: DashboardLayoutProps) {
}
setIsNavigationFullyExpanded(false);
+
+ return () => {};
}, [isNavigationExpanded, theme]);
const selectedItemIdRef = React.useRef('');
@@ -449,8 +450,9 @@ function DashboardLayout(props: DashboardLayoutProps) {
// If useEffect was used, the reset would also happen on the client render after SSR which we don't need
React.useMemo(() => {
- selectedItemIdRef.current = '';
- // eslint-disable-next-line react-hooks/exhaustive-deps
+ if (navigation) {
+ selectedItemIdRef.current = '';
+ }
}, [navigation]);
const isDesktopMini = !disableCollapsibleSidebar && !isDesktopNavigationExpanded;
diff --git a/packages/toolpad-core/src/useNotifications/NotificationsProvider.tsx b/packages/toolpad-core/src/useNotifications/NotificationsProvider.tsx
index af37a13285c..8a7ab8cabb2 100644
--- a/packages/toolpad-core/src/useNotifications/NotificationsProvider.tsx
+++ b/packages/toolpad-core/src/useNotifications/NotificationsProvider.tsx
@@ -141,7 +141,12 @@ export interface NotificationsProviderProps {
slotProps?: Partial;
}
-let nextId = 1;
+let nextId = 0;
+const generateId = () => {
+ const id = nextId;
+ nextId += 1;
+ return id;
+};
/**
* Provider for Notifications. The subtree of this component can use the `useNotifications` hook to
@@ -161,8 +166,7 @@ function NotificationsProvider(props: NotificationsProviderProps) {
const [state, setState] = React.useState({ queue: [] });
const show = React.useCallback((message, options = {}) => {
- const notificationKey = options.key ?? `::toolpad-internal::notification::${nextId}`;
- nextId += 1;
+ const notificationKey = options.key ?? `::toolpad-internal::notification::${generateId()}`;
setState((prev) => {
if (prev.queue.some((n) => n.notificationKey === notificationKey)) {
// deduplicate by key
diff --git a/packages/toolpad-studio/src/utils/useThottled.ts b/packages/toolpad-studio/src/utils/useThottled.ts
deleted file mode 100644
index adcbc5936f0..00000000000
--- a/packages/toolpad-studio/src/utils/useThottled.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import * as React from 'react';
-/**
- * This hook allows you to throttle any fast changing value. The throttle value will only
- * update once in the defined time period. Multiple changes to the value within this time
- * period are throttled until the delay has passed.
- */
-export default function useThrottled(value: T, throttle: number): T {
- const [throttledValue, setThrottledValue] = React.useState(value);
- const lastUpdate = React.useRef(-Infinity);
-
- const updateThrottledValue = React.useCallback((newValue: T) => {
- lastUpdate.current = Date.now();
- setThrottledValue(newValue);
- }, []);
-
- React.useEffect(() => {
- const now = Date.now();
- const elapsed = now - lastUpdate.current;
-
- if (elapsed > throttle) {
- updateThrottledValue(value);
- return () => {};
- }
-
- const delay = throttle - elapsed;
- const timeoutId = setTimeout(() => updateThrottledValue(value), delay);
- return () => clearTimeout(timeoutId);
- }, [value, throttle, updateThrottledValue]);
-
- const now = Date.now();
- const elapsed = now - lastUpdate.current;
-
- return elapsed > throttle ? value : throttledValue;
-}
diff --git a/packages/toolpad-utils/src/hooks/useLatest.ts b/packages/toolpad-utils/src/hooks/useLatest.ts
index 3cb3d8ec904..2c29357b97b 100644
--- a/packages/toolpad-utils/src/hooks/useLatest.ts
+++ b/packages/toolpad-utils/src/hooks/useLatest.ts
@@ -6,13 +6,11 @@ import * as React from 'react';
function useLatest(value: T): T;
function useLatest(value: T | null | undefined): T | null | undefined;
function useLatest(value: T | null | undefined): T | null | undefined {
- const valueRef = React.useRef(value);
- React.useEffect(() => {
- if (value !== null && value !== undefined) {
- valueRef.current = value;
- }
- }, [value]);
- return value ?? valueRef.current;
+ const [latest, setLatest] = React.useState(value);
+ if (latest !== value && value !== null && value !== undefined) {
+ setLatest(value);
+ }
+ return value ?? latest;
}
export default useLatest;