Next.js服务器组件转换为客户端组件时出现问题

jdg4fx2g  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(191)

我正在用next.js开发一个博客网站。我有一个主页,这是一个服务器组件,但现在我想它改变为客户端组件,使我可以使它交互(集成分页)。
但是当我将代码转换为客户端组件时,它开始给我带来一些问题,例如浏览器窗口似乎不时地在本地主机打开时卡住。另外,API请求getPosts方法没有被react的useState的setState函数存储,这有点奇怪。
下面给出的是以前的服务器组件的主页-

import { getCategoryPosts, getPosts } from '@/services'
import styles from '../../app/page.module.scss'
import PostCard from './PostCard'

type Props = { categorySlug?: string }

async function HomePagePosts({ categorySlug = '' }: Props) {
  const { postsContainer } = styles
  let posts
  if (!categorySlug) {
    posts = await getPosts()
  } else {
    posts = await getCategoryPosts(categorySlug)
  }

  return (
    <section className={postsContainer}>
      {posts.map((post) => (
        <PostCard post={post} key={post.title}></PostCard>
      ))}
    </section>
  )
}

export default HomePagePosts

字符串
下面是新的客户端组件-

'use client'

import { useEffect, useState } from 'react'
import { getCategoryPosts, getPosts } from '@/services'
import styles from '../../app/page.module.scss'
import PostCard from './PostCard'

type Props = { categorySlug?: string }

function HomePagePosts({ categorySlug = '' }: Props) {
  const [posts, setPosts] = useState([])

  useEffect(() => {
    async function setAllPosts() {
      if (!categorySlug) {
        setPosts(await getPosts())
      } else {
        setPosts(await getCategoryPosts(categorySlug))
      }
    }
    setAllPosts()
  }, [])

  const { postsContainer } = styles

  return (
    <section className={postsContainer}>
      {posts.map((post) => (
        <PostCard post={post} key={post.title}></PostCard>
      ))}
    </section>
  )
}

export default HomePagePosts


上面的代码导致无限循环,导致窗口被卡住,并且状态呈现为空并且不更新。
但是如果我控制台记录getPosts()方法,它会返回正确的内容,所以这个转换有问题。
编辑-
我注意到一些事-

return (
    <section className={postsContainer}>
      help
      {posts?.map((post) => (
        <div key={post.title}>{post.title}</div>
        // <PostCard post={post} key={post.title}></PostCard>
      ))}
    </section>
  )


上面的代码给出了正确的post.title内容
但是如果我使用<PostCard/>组件,那么只有它保持加载并进入无限循环,并且在posts状态下不显示任何内容。
PostCard组件是一个服务器组件,它是一个异步功能组件,所以这可能是问题吗?
这是明信片的代码--

import { postsType } from '@/utils/types/types'
import styles from '../../app/page.module.scss'
import moment from 'moment'
import Link from 'next/link'
import Image from 'next/image'
import { myPortfolioURL } from '@/services'
import LikeButton from '../buttons/LikeButton'
import CommentButton from '../buttons/CommentButton'

type Props = { post: postsType }

async function PostCard({ post }: Props) {
  const {
    postCard,
    postImage,
    title,
    summary,
    authorName,
    authorInfo,
    authorInfoContainer,
    authorImage,
    date,
    icon,
    userFeedbackContainer,
    leftAlign,
    rightAlign,
    readTimeContainer,
    postReactionSection,
  } = styles
  const authorId: string = (await myPortfolioURL(post.author.id)) || '/'
  return (
    <div className={postCard}>
      <div className={authorInfoContainer}>
        <Link
          href={authorId}
          className={authorInfo}
          rel="noopener noreferrer"
          target="_blank"
        >
          <div className={authorImage}>
            <Image
              src={post.author.photo.url}
              style={{ objectFit: 'cover', borderRadius: '50%' }}
              sizes="(max-width: 768px) 40px, (max-width: 1200px) 50px, 40px"
              fill={true}
              alt={post.author.name}
            />
          </div>
          <p className={authorName}>{post.author.name}</p>
        </Link>

        <div className={date}>
          <p>{moment(post.createdAt).format('MMM DD, YYYY')}</p>
        </div>
      </div>
      <Link href={`/post/${post.slug}`}>
        <div className={postImage}>
          <Image
            src={post.featuredImage.url}
            style={{ objectFit: 'cover', borderRadius: '.5rem' }}
            fill={true}
            alt={post.title}
          />
        </div>
      </Link>

      <h1>
        <Link href={`/post/${post.slug}`} className={title}>
          {post.title}
        </Link>
      </h1>
      <div className={summary}>{post.summary}</div>
      <div className={postReactionSection}>
        <div className={leftAlign}>
          <div className={userFeedbackContainer}>
            <LikeButton postId={post.id} />
            <CommentButton postId={post.id} />
          </div>
        </div>
        <div className={rightAlign}>
          <div className={readTimeContainer}>{post.readTime} min read</div>
        </div>
      </div>
    </div>
  )
}

export default PostCard

8dtrkrch

8dtrkrch1#

不能有异步效果。因此,您需要执行以下操作

useEffect(() => {
    getPosts().then(data => setPosts(data)); 
  }, [])

字符串

更新:

根据更新后的问题。我注意到您正在使用服务器组件PostCard作为client component的子组件。这就是错误的原因。客户端组件的所有子组件始终是客户端组件。
因此,您应该从客户端组件中删除服务器端代码,并使其不异步。

相关问题