I am using latest Next.js app router version. When I load data in my component it initially renders infinite I don't know why. I have valid data.
SidebarContent.tsx
"use client";
import { useEffect, useState } from "react";
import SlidebarItems from "./SlidebarItems";
export default function SlidebarContent() {
const [content, setContent] = useState<any>([]);
useEffect(() => {
async function getData() {
const res = await fetch("/api");
const data = await res.json();
setContent(data);
}
getData();
}, []);
const selectItem = (id: string) => {
const newContent = content.map((item) => {
if (item.id === id) {
return { ...item, show: true };
} else {
return { ...item, show: false };
}
});
setContent(newContent);
};
console.log("renders content");
return (
<div className="flex justify-between items-center h-full w-full">
<div className="sliderRef flex gap-2 items-center h-full w-[85%] overflow-x-hidden">
hi
{content &&
content.map((item) => (
<SlidebarItems
key={item.id}
content={item}
onClick={(id) => selectItem(id)}
/>
))}
</div>
</div>
);
}
SidebarItems.js
"use client";
import Image from "next/image";
const SlidebarItems = async ({ content, onClick }) => {
return (
<div
className={`slidebar-content ${content.show ? "selected" : ""}`}
onClick={() => onClick(content.id)}
>
<div className="flex flex-col items-center w-[98px] ">
<Image
src={content.src}
alt={content.title}
width={24}
height={24}
priority
className="h-7 w-7 mb-2 "
/>
<h3 className="text-xs font-medium">{content.title}</h3>
</div>
</div>
);
};
export default SlidebarItems;
When I add React Suspense it works fine but I don't want React Suspense to use because when it re-renders it shows fallback component. I want to use this as normal re-render not infinite.
In your SidebarItems.js
you define the functional component as async
.
That makes the function return a promise, which is causing this weird endless re-rendering. Removing the async
fixed the issue.
However in your example, I also got some error regarding loading the images
Error: Invalid src prop (https://img.icons8.com/ios/50/key.png) on `next/image`, hostname "img.icons8.com" is not configured under images in your `next.config.js`
which you might have to fix as well. Temporarily fixed it with the loader prop to see if the re-rendering issue really was fixed in the example.