From 0b7fc8b1f22c60c06361ea2b6f1aec6ee8dbf7b7 Mon Sep 17 00:00:00 2001 From: PiyushXmishra Date: Thu, 9 Oct 2025 13:18:56 +0530 Subject: [PATCH] fix: prevent infinite re-render loop in AnimatedGridPattern component --- apps/www/public/llms-full.txt | 21 ++++++++++++------- apps/www/public/r/animated-grid-pattern.json | 2 +- .../magicui/animated-grid-pattern.tsx | 21 ++++++++++++------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/apps/www/public/llms-full.txt b/apps/www/public/llms-full.txt index 528ffc5dd..10ddcb6cb 100644 --- a/apps/www/public/llms-full.txt +++ b/apps/www/public/llms-full.txt @@ -2338,6 +2338,7 @@ Description: A animated background grid pattern made with SVGs, fully customizab import { ComponentPropsWithoutRef, + useCallback, useEffect, useId, useRef, @@ -2375,6 +2376,18 @@ export function AnimatedGridPattern({ const id = useId() const containerRef = useRef(null) const [dimensions, setDimensions] = useState({ width: 0, height: 0 }) + + // Adjust the generateSquares function to return objects with an id, x, and y + const generateSquares = useCallback( + (count: number) => { + return Array.from({ length: count }, (_, i) => ({ + id: i, + pos: getPos(), + })) + }, + [dimensions.width, dimensions.height, width, height] + ) + const [squares, setSquares] = useState(() => generateSquares(numSquares)) function getPos() { @@ -2384,14 +2397,6 @@ export function AnimatedGridPattern({ ] } - // Adjust the generateSquares function to return objects with an id, x, and y - function generateSquares(count: number) { - return Array.from({ length: count }, (_, i) => ({ - id: i, - pos: getPos(), - })) - } - // Function to update a single square's position const updateSquarePosition = (id: number) => { setSquares((currentSquares) => diff --git a/apps/www/public/r/animated-grid-pattern.json b/apps/www/public/r/animated-grid-pattern.json index 3ff60f24e..09f154b29 100644 --- a/apps/www/public/r/animated-grid-pattern.json +++ b/apps/www/public/r/animated-grid-pattern.json @@ -10,7 +10,7 @@ "files": [ { "path": "registry/magicui/animated-grid-pattern.tsx", - "content": "\"use client\"\n\nimport {\n ComponentPropsWithoutRef,\n useEffect,\n useId,\n useRef,\n useState,\n} from \"react\"\nimport { motion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface AnimatedGridPatternProps\n extends ComponentPropsWithoutRef<\"svg\"> {\n width?: number\n height?: number\n x?: number\n y?: number\n strokeDasharray?: number\n numSquares?: number\n maxOpacity?: number\n duration?: number\n repeatDelay?: number\n}\n\nexport function AnimatedGridPattern({\n width = 40,\n height = 40,\n x = -1,\n y = -1,\n strokeDasharray = 0,\n numSquares = 50,\n className,\n maxOpacity = 0.5,\n duration = 4,\n ...props\n}: AnimatedGridPatternProps) {\n const id = useId()\n const containerRef = useRef(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n const [squares, setSquares] = useState(() => generateSquares(numSquares))\n\n function getPos() {\n return [\n Math.floor((Math.random() * dimensions.width) / width),\n Math.floor((Math.random() * dimensions.height) / height),\n ]\n }\n\n // Adjust the generateSquares function to return objects with an id, x, and y\n function generateSquares(count: number) {\n return Array.from({ length: count }, (_, i) => ({\n id: i,\n pos: getPos(),\n }))\n }\n\n // Function to update a single square's position\n const updateSquarePosition = (id: number) => {\n setSquares((currentSquares) =>\n currentSquares.map((sq) =>\n sq.id === id\n ? {\n ...sq,\n pos: getPos(),\n }\n : sq\n )\n )\n }\n\n // Update squares to animate in\n useEffect(() => {\n if (dimensions.width && dimensions.height) {\n setSquares(generateSquares(numSquares))\n }\n }, [dimensions, numSquares, generateSquares])\n\n // Resize observer to update container dimensions\n useEffect(() => {\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n setDimensions({\n width: entry.contentRect.width,\n height: entry.contentRect.height,\n })\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n }\n\n return () => {\n if (containerRef.current) {\n resizeObserver.unobserve(containerRef.current)\n }\n }\n }, [containerRef])\n\n return (\n \n \n \n \n \n \n \n \n {squares.map(({ pos: [x, y], id }, index) => (\n updateSquarePosition(id)}\n key={`${x}-${y}-${index}`}\n width={width - 1}\n height={height - 1}\n x={x * width + 1}\n y={y * height + 1}\n fill=\"currentColor\"\n strokeWidth=\"0\"\n />\n ))}\n \n \n )\n}\n", + "content": "\"use client\"\n\nimport {\n ComponentPropsWithoutRef,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n} from \"react\"\nimport { motion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface AnimatedGridPatternProps\n extends ComponentPropsWithoutRef<\"svg\"> {\n width?: number\n height?: number\n x?: number\n y?: number\n strokeDasharray?: number\n numSquares?: number\n maxOpacity?: number\n duration?: number\n repeatDelay?: number\n}\n\nexport function AnimatedGridPattern({\n width = 40,\n height = 40,\n x = -1,\n y = -1,\n strokeDasharray = 0,\n numSquares = 50,\n className,\n maxOpacity = 0.5,\n duration = 4,\n ...props\n}: AnimatedGridPatternProps) {\n const id = useId()\n const containerRef = useRef(null)\n const [dimensions, setDimensions] = useState({ width: 0, height: 0 })\n\n // Adjust the generateSquares function to return objects with an id, x, and y\n const generateSquares = useCallback(\n (count: number) => {\n return Array.from({ length: count }, (_, i) => ({\n id: i,\n pos: getPos(),\n }))\n },\n [dimensions.width, dimensions.height, width, height]\n )\n\n const [squares, setSquares] = useState(() => generateSquares(numSquares))\n\n function getPos() {\n return [\n Math.floor((Math.random() * dimensions.width) / width),\n Math.floor((Math.random() * dimensions.height) / height),\n ]\n }\n\n // Function to update a single square's position\n const updateSquarePosition = (id: number) => {\n setSquares((currentSquares) =>\n currentSquares.map((sq) =>\n sq.id === id\n ? {\n ...sq,\n pos: getPos(),\n }\n : sq\n )\n )\n }\n\n // Update squares to animate in\n useEffect(() => {\n if (dimensions.width && dimensions.height) {\n setSquares(generateSquares(numSquares))\n }\n }, [dimensions, numSquares, generateSquares])\n\n // Resize observer to update container dimensions\n useEffect(() => {\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n setDimensions({\n width: entry.contentRect.width,\n height: entry.contentRect.height,\n })\n }\n })\n\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n }\n\n return () => {\n if (containerRef.current) {\n resizeObserver.unobserve(containerRef.current)\n }\n }\n }, [containerRef])\n\n return (\n \n \n \n \n \n \n \n \n {squares.map(({ pos: [x, y], id }, index) => (\n updateSquarePosition(id)}\n key={`${x}-${y}-${index}`}\n width={width - 1}\n height={height - 1}\n x={x * width + 1}\n y={y * height + 1}\n fill=\"currentColor\"\n strokeWidth=\"0\"\n />\n ))}\n \n \n )\n}\n", "type": "registry:ui" } ] diff --git a/apps/www/registry/magicui/animated-grid-pattern.tsx b/apps/www/registry/magicui/animated-grid-pattern.tsx index 11ebb4cc3..d46a8ce68 100644 --- a/apps/www/registry/magicui/animated-grid-pattern.tsx +++ b/apps/www/registry/magicui/animated-grid-pattern.tsx @@ -2,6 +2,7 @@ import { ComponentPropsWithoutRef, + useCallback, useEffect, useId, useRef, @@ -39,6 +40,18 @@ export function AnimatedGridPattern({ const id = useId() const containerRef = useRef(null) const [dimensions, setDimensions] = useState({ width: 0, height: 0 }) + + // Adjust the generateSquares function to return objects with an id, x, and y + const generateSquares = useCallback( + (count: number) => { + return Array.from({ length: count }, (_, i) => ({ + id: i, + pos: getPos(), + })) + }, + [dimensions.width, dimensions.height, width, height] + ) + const [squares, setSquares] = useState(() => generateSquares(numSquares)) function getPos() { @@ -48,14 +61,6 @@ export function AnimatedGridPattern({ ] } - // Adjust the generateSquares function to return objects with an id, x, and y - function generateSquares(count: number) { - return Array.from({ length: count }, (_, i) => ({ - id: i, - pos: getPos(), - })) - } - // Function to update a single square's position const updateSquarePosition = (id: number) => { setSquares((currentSquares) =>