NextJS 13:使聊天应用程序中的侧边栏服务器组件失效

NextJS 13: Invalidating sidebar server component in chat app

提问人:wongz 提问时间:11/17/2023 最后编辑:wongz 更新时间:11/17/2023 访问量:8

问:

完整的最小可重现存储库在这里

这是一个具有以下路线的聊天应用程序:

  • /聊天
    • layout.tsx - 包含服务器组件的服务器组件,该组件也是一个服务器组件Sidebar
  • /chat/[id] - 客户端组件

每当我更新组件中的数据时,即使使用以下所有命令,侧边栏也不会更新:Input

router.refresh();
router.push("/chat/" + chatId);

我什至有一个特殊的路由可以使服务器端的缓存失效,该缓存调用但侧边栏仍然没有更新。revalidatePath("/chat", "layout")

但是,这很奇怪,因为在我的服务器组件中,显示它更新了,但 UI 由于某种原因没有更新。Sidebar

下面是一些关键代码片段,但完整的可重现代码位于存储库中。

// ./app/chat/layout.tsx

import React from 'react'
import { Sidebar } from "./_sidebar"

export default async function Layout({children}: {children: React.ReactNode}) {
  return (
    <div className="relative w-screen min-h-screen flex justify-start">
      <Sidebar />
      {children}
    </div>
  )
}
// ./app/chat/_sidebar
import { getChats } from "@/actions";
import Link from "next/link";

export async function Sidebar() {
  const chats = await getChats();
  console.log("Sidebar.chats.latest", chats.at(-1))

  return (
    <div className="flex flex-col h-full px-6 min-h-screen">
      <h2 className="font-bold underline">Sidebar</h2>
        <Link href="/chat">New Chat</Link>
        {chats.map((chat, index) => (
          <p className="whitespace-nowrap" key={index}>{chat.message.slice(0,20)}</p>
         ))}
    </div>
  );
}
// ./app/chat/_input.tsx

"use client";
import { nanoid } from "nanoid";
import { useRouter } from "next/navigation";
import React from "react";

export function Input() {
  const router = useRouter();
  const inputRef = React.useRef<any>();

  return (
    <div className="absolute bottom-1/2 flex flex-col h-28">
      <div className="flex flex-col space-y-8">
        <label className="text-white">Input Field Below:</label>
        <textarea ref={inputRef} className="text-black w-96 h-48" />
        <button
          className="bg-green-900 px-6 py-3"
          onClick={async () => {
            const value = inputRef?.current.value;
            const chatId = nanoid();
            await fetch("/api/chats/update", {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({ id: chatId, message: value }),
            }).then(res => res.json());

            await fetch(`/api/revalidate?path=/chat&type=layout`, {cache: "no-store"});
            router.refresh();
            router.push("/chat/" + chatId);
         }}
        >
          Submit
        </button>
      </div>
    </div>
  );
}
缓存 next.js13

评论

0赞 Mallikarjun M G 11/28/2023
为什么不能定义全局状态存储?...您可以使用 zustand 或 redux。

答:

2赞 Muka Nakazato 11/23/2023 #1

我找到了一个解决方法:只需交换 和 行。 也许它不需要调用.router.pushrouter.refreshrevalidatePath

下面的代码是一个示例。

<button
    className="bg-green-900 px-6 py-3"
    onClick={async () => {
        const value = inputRef?.current.value;
        const chatId = nanoid();
        await fetch("/api/chats/update", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ id: chatId, message: value }),
        }).then(res => res.json());
        router.push("/chat/" + chatId);
        router.refresh();
    }}
>
    Submit
</button>