reactjs 在Next.js 13应用目录中将更改从服务器推送到客户端组件

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

我正在使用Next.js 13的app目录,我想复制一些我在“经典”pages目录中拥有的功能。我想显示一个由卡片组成的网格,每个卡片代表一组主机。我想在后台ping主机,每张卡都应该显示主机是否可达。
一张卡片看起来像这样:
app/clients/client-card.tsx

"use client";

import { Card, CardBody } from "../components";
import { Chip } from "@material-tailwind/react";

export type ClientProps = {
  label: string;
  available?: boolean | undefined;
};

export default function ClientCard({ label, available }: ClientProps) {
  return (
    <Card key={label} title={label}>
      <CardBody>
        <h4>{label}</h4>
        <Chip
          color={available === undefined ? "gray" : available ? "green" : "red"}
          className="mt-2"
          value={available === undefined ? "Checking" : available ? "Online" : "Offline"}
        />
      </CardBody>
    </Card>
  );
}

app/clients/page.tsx中的服务器代码:

import fs from "fs";
import path from "path";
import { load } from "js-yaml";
import ClientCard from "./client-card";

type AnsibleInventory = {
  probes?: {
    hosts: Record<string, unknown>;
  };
};

async function getInventory() {
  const inventoryFile = path.join(
    __dirname,
    "..",
    "..",
    "..",
    "..",
    "..",
    "example",
    "inventory",
    "hosts.yml"
  );
  const inventory = load(
    fs.readFileSync(inventoryFile, "utf8")
  ) as AnsibleInventory;

  return inventory;
}

export default async function Clients() {
  const inventory = await getInventory();

  const isAvailable = async (client: string): Promise<boolean> => {
    const sleep = (ms: number) =>
      new Promise((resolve) => setTimeout(resolve, ms));
    await sleep(1000 + Math.random() * 1000);
    return Math.random() > 0.5;
  };

  return (
    <div>
      <h1>Clients</h1>
      {inventory.probes?.hosts === undefined ? (
        <p>No clients found</p>
      ) : (
        <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
          {Object.keys(inventory.probes?.hosts).map((client) => (
            <div key={client} className="col-span-1">
              <ClientCard
                key={client}
                label={client}
                available={isAvailable(client)}
              />
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

问题是,我希望页面首先加载,每张卡显示一个“检查”状态和灰色芯片,并传播检查结果。每一张卡片上都有。但是我不能异步调用isAvailable()函数它需要一个同步值。我不能在服务器端使用useState和效果。
以前,我可能会创建一个专用的api路由,并从每个客户端卡向服务器发出一个请求,以从API获取fetch的可用性状态。
有没有简单的方法可以做到这一点?特别是,这是一个潜在的长名单卡为个别主机.
我看到在其中一个streaming examples中,fetch被传递到各个组件,但这些组件似乎也是服务器端的。在我的例子中,我显然必须使用"use client";,因为@material-tailwind/react库使用了一些客户端副作用,所以我不能将其作为服务器组件。

qxsslcnc

qxsslcnc1#

现在似乎没有明显的解决方案,除了分离库,这样我就不会在RSC中导入客户端库。

相关问题