next.js 未捕获错误:渲染的钩子比预期的要少,这可能是由React Hooks中意外的提前返回语句引起的,(需要使用Modal)

dbf7pr2w  于 2023-06-29  发布在  React
关注(0)|答案(1)|浏览(136)

嗨,我正试图使我的新闻页面这样一种方式,当用户点击到一个特定的新闻,将有一个弹出模态显示的全部内容的新闻。然而,我的Map中的useModal导致了这个问题。有什么建议可以让我解决这个问题吗?下面是我的代码:

import SortingDate from "@/functions/Sorting";
import { Posts } from "@/data/news-posts";
import { useModal } from "@nextui-org/react";
import NewsModal from "@/components/ui/news-modal";
import { useState, useEffect,  } from "react";
import Loading from "./loading";

function News() {
  const [data, setData] = useState(null);
  const [isLoading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    fetch("/api/news")
      .then((res) => res.json())
      .then((data) => {
        setData(data);
        setLoading(false);
      });
  }, []);

  if (isLoading) return <Loading />;
  if (!data) return <Loading />;

  console.log(data);

  return (
    <div className="py-24">
      <div className="mx-auto max-w-7xl px-6 lg:px-8">
        <div className="mx-auto max-w-2xl text-center">
          <h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">
            Here comes the tea
          </h2>
          <p className="mt-2 text-lg leading-8 text-gray-300">
            Keep in touch with the latest news.
          </p>
        </div>

        {/* <Posts /> */}
        {/* {console.log(Res)} */}
        <div className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-3">
          {SortingDate(data).map((post) => {
            const { setVisible, bindings } = useModal();
            return (
              <button
                onClick={() => setVisible((prevState) => !prevState)}
                key={post.id}
                className="flex flex-col items-start bg-gray-800 rounded-2xl"
              >
                <NewsModal
                  setVisible={setVisible}
                  bindings={bindings}
                  id={post.id}
                />
                <article key={post.id}>
                  <div className="relative w-full">
                    <img
                      src={post.imageUrl}
                      alt="Thumbnail"
                      className="aspect-[16/9] w-full rounded-2xl bg-gray-300 object-cover sm:aspect-[2/1] lg:aspect-[3/2]"
                    />
                    <div className="absolute inset-0 rounded-2xl ring-1 ring-inset ring-gray-900/10" />
                  </div>
                  <div className="max-w-xl">
                    <div className="mt-8 flex items-center gap-x-4 text-xs mx-2">
                      <time dateTime={post.datetime} className="text-gray-300">
                        {post.date}
                      </time>
                      {/* <a
                    href={post.category.href}
                    className="relative z-10 rounded-full bg-gray-50 px-3 py-1.5 font-medium text-gray-600 hover:bg-gray-100"
                  >
                    {post.category.title}
                  </a> */}
                    </div>
                    <div className="group relative mx-2">
                      <h3 className="mt-3 text-lg font-semibold leading-6 text-gray-300 group-hover:text-gray-500">
                        <a href={post.href}>
                          <span className="absolute inset-0" />
                          {post.title}
                        </a>
                      </h3>
                      {/* <p className="mt-5 line-clamp-3 text-sm leading-6 text-gray-300">
                    {post.description}
                  </p> */}
                    </div>
                    <div className="relative mt-8 flex items-center gap-x-4 mx-2 my-2">
                      <div className="text-sm leading-6">
                        <p className="font-semibold text-white">
                          <a>
                            <span className="absolute inset-0" />
                            {post.author.name}
                          </a>
                        </p>
                      </div>
                    </div>
                  </div>
                </article>
              </button>
            );
          })}
        </div>
      </div>
    </div>
  );
}

我试过将我的加载条件放入useEffect中,但我认为不应该这样使用它。

f5emj3cl

f5emj3cl1#

在这种情况下,一个很好的做法是将你想要渲染的代码放在map函数中,然后用它创建另一个React组件。
这可以使您的应用程序代码看起来更干净,但也可以避免直接在map函数中使用useModal钩子。
我刚才提到的实现看起来像这样:

export default function NewsButton({ post }) {
  const { setVisible, bindings } = useModal();

  return (
    <button
      onClick={() => setVisible((prevState) => !prevState)}
      key={post.id}
      className="flex flex-col items-start bg-gray-800 rounded-2xl"
    >
      <NewsModal setVisible={setVisible} bindings={bindings} id={post.id} />
      <article key={post.id}>
        <div className="relative w-full">
          <img
            src={post.imageUrl}
            alt="Thumbnail"
            className="aspect-[16/9] w-full rounded-2xl bg-gray-300 object-cover sm:aspect-[2/1] lg:aspect-[3/2]"
          />
          <div className="absolute inset-0 rounded-2xl ring-1 ring-inset ring-gray-900/10" />
        </div>
        <div className="max-w-xl">
          <div className="mt-8 flex items-center gap-x-4 text-xs mx-2">
            <time dateTime={post.datetime} className="text-gray-300">
              {post.date}
            </time>
            {/* <a
                      href={post.category.href}
                      className="relative z-10 rounded-full bg-gray-50 px-3 py-1.5 font-medium text-gray-600 hover:bg-gray-100"
                    >
                      {post.category.title}
                    </a> */}
          </div>
          <div className="group relative mx-2">
            <h3 className="mt-3 text-lg font-semibold leading-6 text-gray-300 group-hover:text-gray-500">
              <a href={post.href}>
                <span className="absolute inset-0" />
                {post.title}
              </a>
            </h3>
            {/* <p className="mt-5 line-clamp-3 text-sm leading-6 text-gray-300">
                      {post.description}
                    </p> */}
          </div>
          <div className="relative mt-8 flex items-center gap-x-4 mx-2 my-2">
            <div className="text-sm leading-6">
              <p className="font-semibold text-white">
                <a>
                  <span className="absolute inset-0" />
                  {post.author.name}
                </a>
              </p>
            </div>
          </div>
        </div>
      </article>
    </button>
  );
}
import SortingDate from "@/functions/Sorting";
import { Posts } from "@/data/news-posts";
import { useModal } from "@nextui-org/react";
import NewsModal from "@/components/ui/news-modal";
import { useState, useEffect,  } from "react";
import Loading from "./loading";

import NewsButton from '@/components/ui/news-button';

function News() {
  const [data, setData] = useState(null);
  const [isLoading, setLoading] = useState(false);

  useEffect(() => {
    setLoading(true);
    fetch("/api/news")
      .then((res) => res.json())
      .then((data) => {
        setData(data);
        setLoading(false);
      });
  }, []);

  if (isLoading) return <Loading />;
  if (!data) return <Loading />;

  console.log(data);

  return (
    <div className="py-24">
      <div className="mx-auto max-w-7xl px-6 lg:px-8">
        <div className="mx-auto max-w-2xl text-center">
          <h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">
            Here comes the tea
          </h2>
          <p className="mt-2 text-lg leading-8 text-gray-300">
            Keep in touch with the latest news.
          </p>
        </div>

        {/* <Posts /> */}
        {/* {console.log(Res)} */}
        <div className="mx-auto mt-16 grid max-w-2xl grid-cols-1 gap-x-8 gap-y-20 lg:mx-0 lg:max-w-none lg:grid-cols-3">
          {SortingDate(data).map((post) => {
            return <NewsButton post={post}/>
          })}
        </div>
      </div>
    </div>
  );
}

相关问题