Skip to content

Commit 0b56eb0

Browse files
committed
Add the React Compiler
1 parent c9e91d2 commit 0b56eb0

File tree

9 files changed

+178
-129
lines changed

9 files changed

+178
-129
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: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -601,10 +601,14 @@ 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+
// also ensures we have a stable reference to the style object
607+
const [skeletonStyle] = React.useState(() => (
608+
{
609+
"--skeleton-width": `${Math.floor(Math.random() * 40) + 50}%` // Random width between 50 to 90%.
610+
} as React.CSSProperties
611+
))
608612

609613
return (
610614
<div
@@ -622,11 +626,7 @@ function SidebarMenuSkeleton({
622626
<Skeleton
623627
className="h-4 max-w-(--skeleton-width) flex-1"
624628
data-sidebar="menu-skeleton-text"
625-
style={
626-
{
627-
"--skeleton-width": width,
628-
} as React.CSSProperties
629-
}
629+
style={skeletonStyle}
630630
/>
631631
</div>
632632
)

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
}

resources/js/pages/welcome.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,7 @@ export default function Welcome() {
232232
strokeWidth={1}
233233
/>
234234
</g>
235-
<g
236-
/** @ts-expect-error 'plus-darker' doesn't seem to be defined in the 'csstype' module */
237-
style={{ mixBlendMode: 'plus-darker' }}
238-
className="translate-y-0 opacity-100 transition-all delay-300 duration-750 starting:translate-y-4 starting:opacity-0"
239-
>
235+
<g className="translate-y-0 opacity-100 mix-blend-plus-darker transition-all delay-300 duration-750 starting:translate-y-4 starting:opacity-0">
240236
<path
241237
d="M230.951 281.792L231.282 281.793C238.128 274.907 248.453 265.823 262.256 254.539C275.617 243.256 285.666 234.267 292.402 227.573C299.027 220.688 303.554 213.421 305.983 205.771C308.412 198.12 307.253 190.183 302.504 181.959C297.203 172.778 289.749 165.415 280.142 159.868C270.645 154.13 260.596 151.26 249.995 151.26C239.615 151.26 232.823 154.033 229.621 159.579C226.309 164.934 227.413 172.393 232.935 181.956L168.335 181.954C159.058 165.888 155.082 151.543 156.407 138.92C157.953 126.298 164.247 116.544 175.289 109.659C186.442 102.583 201.294 99.045 219.846 99.0457C239.281 99.0464 258.551 102.585 277.655 109.663C296.649 116.549 313.986 126.303 329.667 138.927C345.349 151.551 357.827 165.895 367.104 181.961C375.718 196.88 379.528 209.981 378.535 221.265C377.762 232.549 374.063 242.399 367.438 250.814C361.033 259.229 351.095 269.557 337.624 281.796L419.782 281.8L448.605 331.719L259.774 331.712L230.951 281.792Z"
242238
fill="#F3BEC7"

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)