我习惯了以前的Next.js体系 struct ,并开始了一个新项目,try 将新体系 struct 与服务器和客户端组件结合使用.

我有一个页面,这是一个比赛结果表,需要在服务器上呈现的SEO目的.一旦页面加载,我想有一个过滤器输入字段,让用户找到他们正在寻找的运动员.

我对怎么做感到有点困惑,我觉得这是不可能的.我try 像以前的体系 struct 一样使用getServerSideProps函数,但在新的体系 struct 上不起作用.

你知道怎么做吗?下面是我的页面代码的实际外观:

const RaceResultsPage = async ({ params }: { params: { raceId: string } }) => {
    const result = await getResultByRaceId(+params.raceId);

    return (
        <>
            <div>
                {/* The input I want to use to filter the table*/}
                <div className="relative mt-2 rounded-md shadow-sm">
                    <div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
                        <MagnifyingGlassIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
                    </div>
                    <input
                        type="email"
                        name="email"
                        id="email"
                        className="block w-full rounded-md border-0 py-1.5 pl-10 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
                        placeholder="Filtrer par nom, prénom, numéro, club"
                    />
                </div>
            </div>

            <div className="mt-8 flow-root">
                <div className="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
                    <div className="inline-block min-w-full py-2 align-middle">
                        <table className="min-w-full divide-y divide-gray-300">
                            <thead>
                            <tr>
                                <th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
                                    Pos.
                                </th>
                                <th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
                                    Bib.
                                </th>
                                <th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
                                    Nom
                                </th>
                                <th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
                                    Cat
                                </th>
                                <th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
                                    Temps
                                </th>
                                <th scope="col" className="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
                                    Ecart
                                </th>
                            </tr>
                            </thead>
                            <tbody className="divide-y divide-gray-200 bg-white">
                            {result.map((person) => (
                                <tr key={person.bib}>
                                    <td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{person.pos}</td>
                                    <td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{person.bib}</td>
                                    <td className="whitespace-nowrap px-3 py-4 text-sm font-medium text-gray-900">
                                        {person.name}
                                    </td>
                                    <td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{person.catRank}</td>
                                    <td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{person.totalTime}</td>
                                    <td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{person.diff}</td>
                                </tr>
                            ))}
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </>
    );
};

我使用的是Next.js 14.

推荐答案

如果您希望您的页面成为服务器组件,使用过滤器的唯一方法是在URL中重新加载页面,例如query string.

但是,要更新URL,您需要一个客户端组件,同时将页面本身保持为服务器组件.

例如,您可以这样做:

// app/SetQueryFilters.tsx

"use client";

import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useCallback } from "react";

export default function SetQueryFilters() {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();

  const createQueryString = useCallback(
    (name: string, value: string) => {
      const params = new URLSearchParams(searchParams.toString());
      params.set(name, value);

      return params.toString();
    },
    [searchParams]
  );

  return (
    <>
      <input
        type="text"
        value={searchParams.get("filter") || ""}
        onChange={(e) => {
          router.push(pathname + "?" + createQueryString("filter", e.target.value));
        }}
      />
    </>
  );
}
// app/page.tsx

import { Suspense } from "react";
import SetQueryFilters from "./SetQueryFilters";

const RaceResultsPage = async ({
  params,
  searchParams,
}: {
  params: { raceId: string };
  searchParams: { filter: string };
}) => {
  const result = await fetch("https://jsonplaceholder.typicode.com/users");
  let data = await result.json();
  data = data.filter((person) => {
    if (searchParams.filter) {
      return person.name.toLowerCase().includes(searchParams.filter.toLowerCase());
    }
    return true;
  });
  return (
    <>
      <Suspense fallback={<div>Loading...</div>}>
        <SetQueryFilters />
      </Suspense>
      <table>
        <thead>
          <tr>
            <th scope="col">Name</th>
            <th scope="col">Username</th>
            <th scope="col">Email</th>
          </tr>
        </thead>
        <tbody>
          {data.map((person) => (
            <tr key={person.id}>
              <td>{person.name}</td>
              <td>{person.username}</td>
              <td>{person.email}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </>
  );
};

export default RaceResultsPage;

Javascript相关问答推荐

主要内部的ExtJS多个子应用程序

如何访问Json返回的ASP.NET Core 6中的导航图像属性

Phaser框架-将子对象附加到Actor

如何在RTK上设置轮询,每24小时

Snowflake JavaScript存储过程返回成功,尽管预期失败

为什么我的列表直到下一次提交才更新值/onChange

无法使用单击按钮时的useState将数据从一个页面传递到另一个页面

查询参数未在我的Next.js应用路由接口中定义

DOM不自动更新,尽管运行倒计时TS,JS

邮箱密码重置链接不适用于已部署的React应用程序

钛中的onClick事件需要在两次点击之间等待几秒钟

无法设置RazorPay订阅API项目价格

Django导入问题,无法导入我的应用程序,但我已在设置中安装了它

如何使用Reaction路由导航测试挂钩?

固定动态、self 调整的优先级队列

如何在Highlihte.js代码区旁边添加行号?

是否有静态版本的`instanceof`?

JavaScript -如何跳过某个字符(S)来打乱字符串中的字符

如何使用Angular JS双击按钮

为什么我的Reaction组件不能使用createBrowserRouter呈现?