Skip to content

Commit b3c6462

Browse files
committed
Add the React Compiler
1 parent c9e91d2 commit b3c6462

File tree

8 files changed

+176
-124
lines changed

8 files changed

+176
-124
lines changed

eslint.config.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import typescript from 'typescript-eslint';
88
/** @type {import('eslint').Linter.Config[]} */
99
export default [
1010
js.configs.recommended,
11+
reactHooks.configs.flat.recommended,
1112
...typescript.configs.recommended,
1213
{
1314
...react.configs.flat.recommended,
@@ -28,15 +29,6 @@ export default [
2829
},
2930
},
3031
},
31-
{
32-
plugins: {
33-
'react-hooks': reactHooks,
34-
},
35-
rules: {
36-
'react-hooks/rules-of-hooks': 'error',
37-
'react-hooks/exhaustive-deps': 'warn',
38-
},
39-
},
4032
{
4133
ignores: ['vendor', 'node_modules', 'public', 'bootstrap/ssr', 'tailwind.config.js'],
4234
},

package-lock.json

Lines changed: 132 additions & 73 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
"@eslint/js": "^9.19.0",
1515
"@laravel/vite-plugin-wayfinder": "^0.1.3",
1616
"@types/node": "^22.13.5",
17+
"babel-plugin-react-compiler": "^1.0.0",
1718
"eslint": "^9.17.0",
1819
"eslint-config-prettier": "^10.0.1",
1920
"eslint-plugin-react": "^7.37.3",
20-
"eslint-plugin-react-hooks": "^5.1.0",
21+
"eslint-plugin-react-hooks": "^7.0.0",
2122
"prettier": "^3.4.2",
2223
"prettier-plugin-organize-imports": "^4.1.0",
2324
"prettier-plugin-tailwindcss": "^0.6.11",
@@ -40,18 +41,18 @@
4041
"@radix-ui/react-toggle-group": "^1.1.2",
4142
"@radix-ui/react-tooltip": "^1.1.8",
4243
"@tailwindcss/vite": "^4.1.11",
43-
"@types/react": "^19.0.3",
44-
"@types/react-dom": "^19.0.2",
45-
"@vitejs/plugin-react": "^4.6.0",
44+
"@types/react": "^19.2.0",
45+
"@types/react-dom": "^19.2.0",
46+
"@vitejs/plugin-react": "^5.0.0",
4647
"class-variance-authority": "^0.7.1",
4748
"clsx": "^2.1.1",
4849
"concurrently": "^9.0.1",
4950
"globals": "^15.14.0",
5051
"input-otp": "^1.4.2",
5152
"laravel-vite-plugin": "^2.0",
5253
"lucide-react": "^0.475.0",
53-
"react": "^19.0.0",
54-
"react-dom": "^19.0.0",
54+
"react": "^19.2.0",
55+
"react-dom": "^19.2.0",
5556
"tailwind-merge": "^3.0.1",
5657
"tailwindcss": "^4.0.0",
5758
"tailwindcss-animate": "^1.0.7",

resources/js/components/two-factor-setup-modal.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -294,19 +294,18 @@ export default function TwoFactorSetupModal({
294294
}, [twoFactorEnabled, clearSetupData]);
295295

296296
useEffect(() => {
297-
if (!isOpen) {
298-
resetModalState();
299-
300-
return;
301-
}
302-
303-
if (!qrCodeSvg) {
297+
if (isOpen && !qrCodeSvg) {
304298
fetchSetupData();
305299
}
306300
}, [isOpen, qrCodeSvg, fetchSetupData, resetModalState]);
307301

302+
const handleClose = useCallback(() => {
303+
resetModalState();
304+
onClose();
305+
}, [onClose, resetModalState]);
306+
308307
return (
309-
<Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
308+
<Dialog open={isOpen} onOpenChange={(open) => !open && handleClose()}>
310309
<DialogContent className="sm:max-w-md">
311310
<DialogHeader className="flex items-center justify-center">
312311
<GridScanIcon />

resources/js/components/ui/sidebar.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -601,10 +601,13 @@ function SidebarMenuSkeleton({
601601
}: React.ComponentProps<"div"> & {
602602
showIcon?: boolean
603603
}) {
604-
// Random width between 50 to 90%.
605-
const width = React.useMemo(() => {
606-
return `${Math.floor(Math.random() * 40) + 50}%`
607-
}, [])
604+
605+
// wrapping in useState to ensure the width is stable across renders
606+
const [skeletonStyle] = React.useState(() => (
607+
{
608+
"--skeleton-width": `${Math.floor(Math.random() * 40) + 50}%` // Random width between 50 to 90%.
609+
} as React.CSSProperties
610+
))
608611

609612
return (
610613
<div
@@ -622,11 +625,7 @@ function SidebarMenuSkeleton({
622625
<Skeleton
623626
className="h-4 max-w-(--skeleton-width) flex-1"
624627
data-sidebar="menu-skeleton-text"
625-
style={
626-
{
627-
"--skeleton-width": width,
628-
} as React.CSSProperties
629-
}
628+
style={skeletonStyle }
630629
/>
631630
</div>
632631
)

resources/js/hooks/use-appearance.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ export function useAppearance() {
6969
const savedAppearance = localStorage.getItem(
7070
'appearance',
7171
) as Appearance | null;
72+
73+
// eslint-disable-next-line react-hooks/set-state-in-effect
7274
updateAppearance(savedAppearance || 'system');
7375

7476
return () =>

resources/js/hooks/use-mobile.tsx

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
1-
import { useEffect, useState } from 'react';
1+
import { useSyncExternalStore } from 'react';
22

33
const MOBILE_BREAKPOINT = 768;
44

5-
export function useIsMobile() {
6-
const [isMobile, setIsMobile] = useState<boolean>();
7-
8-
useEffect(() => {
9-
const mql = window.matchMedia(
10-
`(max-width: ${MOBILE_BREAKPOINT - 1}px)`,
11-
);
12-
13-
const onChange = () => {
14-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
15-
};
5+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
166

17-
mql.addEventListener('change', onChange);
18-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
19-
20-
return () => mql.removeEventListener('change', onChange);
21-
}, []);
7+
function mediaQueryListener(callback: (event: MediaQueryListEvent) => void) {
8+
mql.addEventListener('change', callback);
9+
return () => {
10+
mql.removeEventListener('change', callback);
11+
};
12+
}
2213

23-
return !!isMobile;
14+
export function useIsMobile() {
15+
return useSyncExternalStore(
16+
mediaQueryListener, // React won't resubscribe for as long as you pass the same function
17+
() => window.innerWidth < MOBILE_BREAKPOINT, // How to get the value on the client
18+
() => false, // How to get the value on the server
19+
);
2420
}

vite.config.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ export default defineConfig({
1111
ssr: 'resources/js/ssr.tsx',
1212
refresh: true,
1313
}),
14-
react(),
14+
react({
15+
babel: {
16+
plugins: ['babel-plugin-react-compiler'],
17+
},
18+
}),
1519
tailwindcss(),
1620
wayfinder({
1721
formVariants: true,

0 commit comments

Comments
 (0)