我必须找到不同的方法来完成本教程,例如使用我部署的应用程序为我的 postgres 数据库播种,而不是通过我的本地数据库,这让我不得不从 github UI 通过 VS code 进行编码。
到目前为止一切都很好,再次按照每条指令操作,像往常一样,控制台日志报告了它们应该报告的数据。当我的页面应该能够搜索种子数据时,我在 github 上收到一条错误,该错误来自 vercels 的重新部署失败,指出:
x“导入”和“导出”不能在模块代码之外使用 ,-[/vercel/path0/app/dashboard/invoices/page.tsx:17:1]
https://nextjs.org/learn/dashboard-app/adding-search-and-pagination
我知道本教程中的所有概念尚未达到完全稳定...我希望获得指导和帮助,以解决此问题(如果其他人遇到并克服了该问题)?
我访问过不同的论坛,尽管他们有类似的错误,但他们谈论不同的项目时没有触及我的问题的具体情况。他们使用的技术适用于他们的项目,因为我的项目具体只是分页和搜索功能的特定部分。
这是给整个项目带来错误的两个文件的代码:
//
import Pagination from '@/app/ui/invoices/pagination';
import Search from '@/app/ui/search';
import Table from '@/app/ui/invoices/table';
import { CreateInvoice } from '@/app/ui/invoices/buttons';
import { lusitana } from '@/app/ui/fonts';
import { fetchLatestInvoices} from '@/app/lib/data';
import { Suspense } from 'react';
export default async function Page({
searchParams,
}: {
searchParams?: {
query?: string;
page?: string;
};
}) {
const query = searchParams?.query || '';
const currentPage = Number(searchParams?.page) || 1;
export default async function Page() {
return (
<div className="w-full">
<div className="flex w-full items-center justify-between">
<h1 className={`${lusitana.className} text-2xl`}>Invoices</h1>
</div>
<div className="mt-4 flex items-center justify-between gap-2 md:mt-8">
<Search placeholder="Search invoices..." />
<CreateInvoice />
</div>
{ <Suspense key={query + currentPage} fallback={<InvoicesTableSkeleton />}>
<Table query={query} currentPage={currentPage} />
</Suspense> }
<div className="mt-5 flex w-full justify-center">
{ <Pagination totalPages={totalPages} /> }
</div>
</div>
);
}
//
//
'use client';
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import { useSearchParams, usePathname, useRouter } from 'next/navigation';
export default function Search({ placeholder }: { placeholder: string }) {
const searchParams = useSearchParams();
const pathname = usePathname();
const { replace } = useRouter();
function handleSearch(term: string) {
const params = new URLSearchParams(searchParams);
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
replace(`${pathname}?${params.toString()}`);
console.log(term);
}
return (
<div className="relative flex flex-1 flex-shrink-0">
<label htmlFor="search" className="sr-only">
Search
</label>
<input
className="peer block w-full rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-2 placeholder:text-gray-500"
placeholder={placeholder}
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
<MagnifyingGlassIcon className="absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-gray-500 peer-focus:text-gray-900" />
</div>
);
}
//
首先,您需要标记问题中的文件。我假设第一个列表是 app/dashboard/invoices/page.tsx。
在该文件中,
export default async function Page()
位于export default async function Page()
的主体内。这显然是剪切/粘贴错误。
将第二个
export default async function Page()
替换为:
const totalPages = await fetchInvoicesPages(query);
,因为函数体正在引用 totalPages
。
事实上,您还需要在 page.tsx 顶部包含一条 import 语句:
import { fetchInvoicesPages } from '@/app/lib/data';