最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - Hydration failed because the server rendered HTML didn't match the client error in usage with shadcn-ui card c

programmeradmin3浏览0评论

I am getting this error when I call shadcnui's card component in my next js 15 application. Here are my codes ;

import { Card, CardContent, CardFooter, CardHeader, CardTitle, } from "./ui/card";

export default function CardCategory({
  title,
  summary,
  date,
}: {
  title: string;
  summary: string;
  date: string;
}) {
  return (
    <Card className="w-[350px] h-[290px] shadow-lg">
      <CardHeader>
        <CardTitle>{title}</CardTitle>
      </CardHeader>
      <CardContent>
        <p>{summary}</p>
      </CardContent>
      <CardFooter>
        <p className="text-xs text-gray-500">{date}</p>
      </CardFooter>
    </Card>
  );
}

and this code ;

import CardCategory from "@/components/CardCategory";
import Container from "@/components/Container";
import { Link } from "lucide-react";
import { notFound } from "next/navigation";
import { use } from "react";
import { getBlogPosts } from "../utils";

export function generateStaticParams() {
  let posts = getBlogPosts();

  return posts.map((post) => ({
    category: post.metadata.category,
  }));
}

export async function generateMetadata({
  params,
}: {
  params: Promise<{ category: string }>;
}) {
  let { category } = await params;

  return {
    title: category.toLocaleUpperCase(),
    description: `All articles reagarding ${category}`,
  };
}

export default function Page({
  params,
}: {
  params: Promise<{ category: string }>;
}) {
  let { category } = use(params);

  let posts = getBlogPosts().filter(
    (post) => post.metadata.category === category
  );

  if (!posts) {
    notFound();
  }
  return (
    <>
      <Container>
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-10">
          {posts
            .sort((a, b) => {
              if (
                new Date(a.metadata.publishedAt) >
                new Date(b.metadata.publishedAt)
              ) {
                return -1;
              }
              return 1;
            })
            .map((post) => (
              <Link
                href={`/blog/${post.metadata.category}/${post.slug}`}
                key={post.slug}
              >
                <CardCategory
                  title={post.metadata.title}
                  summary={post.metadata.summary}
                  date={post.metadata.publishedAt}
                />
              </Link>
            ))}
        </div>
      </Container>
    </>
  );
}

Lastly, here is the image of the error I see in the browser ;

I've been trying to solve the error for about 4 hours. I've tried everything in Next js' own documentation. I also looked here but couldn't solve the error.

Thank you in advance for your help.

I am getting this error when I call shadcnui's card component in my next js 15 application. Here are my codes ;

import { Card, CardContent, CardFooter, CardHeader, CardTitle, } from "./ui/card";

export default function CardCategory({
  title,
  summary,
  date,
}: {
  title: string;
  summary: string;
  date: string;
}) {
  return (
    <Card className="w-[350px] h-[290px] shadow-lg">
      <CardHeader>
        <CardTitle>{title}</CardTitle>
      </CardHeader>
      <CardContent>
        <p>{summary}</p>
      </CardContent>
      <CardFooter>
        <p className="text-xs text-gray-500">{date}</p>
      </CardFooter>
    </Card>
  );
}

and this code ;

import CardCategory from "@/components/CardCategory";
import Container from "@/components/Container";
import { Link } from "lucide-react";
import { notFound } from "next/navigation";
import { use } from "react";
import { getBlogPosts } from "../utils";

export function generateStaticParams() {
  let posts = getBlogPosts();

  return posts.map((post) => ({
    category: post.metadata.category,
  }));
}

export async function generateMetadata({
  params,
}: {
  params: Promise<{ category: string }>;
}) {
  let { category } = await params;

  return {
    title: category.toLocaleUpperCase(),
    description: `All articles reagarding ${category}`,
  };
}

export default function Page({
  params,
}: {
  params: Promise<{ category: string }>;
}) {
  let { category } = use(params);

  let posts = getBlogPosts().filter(
    (post) => post.metadata.category === category
  );

  if (!posts) {
    notFound();
  }
  return (
    <>
      <Container>
        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-10">
          {posts
            .sort((a, b) => {
              if (
                new Date(a.metadata.publishedAt) >
                new Date(b.metadata.publishedAt)
              ) {
                return -1;
              }
              return 1;
            })
            .map((post) => (
              <Link
                href={`/blog/${post.metadata.category}/${post.slug}`}
                key={post.slug}
              >
                <CardCategory
                  title={post.metadata.title}
                  summary={post.metadata.summary}
                  date={post.metadata.publishedAt}
                />
              </Link>
            ))}
        </div>
      </Container>
    </>
  );
}

Lastly, here is the image of the error I see in the browser ;

I've been trying to solve the error for about 4 hours. I've tried everything in Next js' own documentation. I also looked here but couldn't solve the error.

Thank you in advance for your help.

Share Improve this question asked Mar 7 at 10:20 Gökhan EkiciGökhan Ekici 133 bronze badges 1
  • Unfortunately this method have not solved that problem. What could be mismatched the server rendered HTML between client rendered HTML ? – Gökhan Ekici Commented Mar 8 at 15:00
Add a comment  | 

2 Answers 2

Reset to default 0

It typically happens when the HTML generated on the server doesn't match the HTML generated on the client.

  • Make sure that the data used to render the component on the server is the same as the data used on the client. Any differences can cause hydration issues.

  • If you have any conditional rendering logic, ensure that it behaves the same on both the server and the client

  • If you have any code that should only run on the client, wrap it in a useEffect hook to ensure it doesn't run during server-side rendering.

  • Add some debugging logs to see what the server and client are rendering. This can help identify where the mismatch is happening.

You might modify your CardCategory component to use useEffect for client-side only code:

import { useEffect, useState } from "react";
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "./ui/card";

export default function CardCategory({
  title,
  summary,
  date,
}: {
  title: string;
  summary: string;
  date: string;
}) {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    setIsClient(true);
  }, []);

  if (!isClient) {
    return null; // or a loading spinner
  }

  return (
    <Card className="w-[350px] h-[290px] shadow-lg">
      <CardHeader>
        <CardTitle>{title}</CardTitle>
      </CardHeader>
      <CardContent>
        <p>{summary}</p>
      </CardContent>
      <CardFooter>
        <p className="text-xs text-gray-500">{date}</p>
      </CardFooter>
    </Card>
  );
}

This ensures that the CardCategory component only renders on the client side, which can help avoid hydration issues.

Note: Sometimes, hydration issues can be environment-specific. Please check if there are any differences in the environment or configuration between your development and production builds

CardDescription is required, missing it may show an error.

import { Card, CardContent, CardFooter, CardHeader, CardTitle, CardDescription  } from "./ui/card";

export default function CardCategory({
  title,
  summary,
  date,
}: {
  title: string;
  summary: string;
  date: string;
}) {
  return (
    <Card className="w-[350px] h-[290px] shadow-lg">
      <CardHeader>
        <CardTitle>{title}</CardTitle>
        <CardDescription className="hidden"></CardDescription> {/* Add this line */}
      </CardHeader>
      <CardContent>
        <p>{summary}</p>
      </CardContent>
      <CardFooter>
        <p className="text-xs text-gray-500">{date}</p>
      </CardFooter>
    </Card>
  );
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论