在 Next.js 的客户端组件中使用异步 React Server 组件时需要使用 Suspense 吗?

问题描述 投票:0回答:1

我正在学习 Next.js,并且我正在尝试在客户端组件内渲染服务器异步组件:

画廊.tsx

import { get_images } from '@/utils';
import styles from './Gallery.module.css';

export default async function Gallery() {
  const images = await get_images();
  return (
    <ul className={styles.gallery}>
      {images.map(file => {
        const url = `https://example.com/images/${file}`;
        return (
          <li key={file}>
            <span>
              {/* when using Image got a double error */}
              <img src={url} alt="image" />
            </span>
          </li>
        );
      })}
    </ul>
  );
}

页面.tsx

'use client';
import { useRef } from 'react';
import { revalidatePath } from 'next/cache'

import styles from "./page.module.css";
import { upload } from '@/git';
import Gallery from '@/components/Gallery';

export default function Home() {
  const formRef = useRef();

  async function uploadAction(formData: FormData) {
    await upload(formData);
    revalidatePath('/');
  }
  
  return (
    <main className={styles.main}>
      {/* <Gallery /> */}
      <h2>Upload form</h2>
      <div className={styles.form}>
        <form action={uploadAction}>
        </form>
      </div>
   </main>
  );
}

我正在重构过程中,我想用useRef向表单添加重置,所以我添加了

use client
。当我将 Gallery 提取到另一个组件中后,开始出现错误:

app-index.js:33 Warning: async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding `'use client'` to a module that was originally written for the server.
    at Gallery
    at main
    at Home (webpack-internal:///(app-pages-browser)/./src/app/page.tsx:23:66)

如果我将``use server'`添加到图库,我收到此错误:

app-index.js:33 Warning: Cannot update a component (`Router`) while rendering a different component (`proxy`). To locate the bad setState() call inside `proxy`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
    at proxy
    at main
    at Home (webpack-internal:///(app-pages-browser)/./src/app/page.tsx:23:66)

添加React.Suspense就解决了所有问题:

      <Suspense fallback={<p>loading...</p>}>
        <Gallery />
      </Suspense>

那么问题来了,使用异步服务器组件时Suspense是必须的吗?我只知道什么是允许的,通过询问这个我不在乎它是否会冻结直到异步操作完成。

我问ChatGPT,它首先给出的答案是您可以将服务器组件包含在客户端组件中。当我问及悬念时,他只提到了延迟。我问的是不使用 Suspense 时出现的神秘错误。

这看起来很常见,但我找不到任何它是如何工作的。

reactjs next.js async-await react-server-components
1个回答
0
投票

在客户端组件中导入服务器组件在 Next.js 中不是有效模式

正确的方法是 将服务器组件作为 prop 传递给客户端组件,并且一般来说,将客户端组件沿着你的 组件树移动。

所以你不需要使用Suspense(因为你将完全避免将服务器组件导入到客户端组件)。 在某种程度上,通过使用 Suspense,您正在“欺骗”Next.js,使其不返回实际上应该返回的错误。

针对这个特定场景,您可以采取多种方法。在您的情况下,最简单的方法可能是将您的主页和图库保留为常规服务器组件,并使您的表单成为客户端组件:然后您可以在其中使用 useRef ,然后将其导入到您的主页中。

© www.soinside.com 2019 - 2024. All rights reserved.