NextJS 13 SSG构建时出现Uncaught SyntaxError错误求助
NextJS 13 SSG构建时
Uncaught SyntaxError: Unexpected string问题分析与解决 问题原因
你的页面是静态生成(SSG)的服务器组件,而<Pagination>客户端组件中使用了useSearchParams()钩子:
useSearchParams()是NextJS专为客户端运行时设计的钩子,只能在浏览器环境中获取当前URL的搜索参数。- 静态构建阶段(
npm run build)NextJS会尝试序列化客户端组件代码,但此时无法解析useSearchParams()的运行时逻辑,导致生成的代码出现语法错误。 - 开发模式下是动态渲染,钩子能正常执行,所以无异常。
解决方案
核心思路:将服务器组件已获取的searchParams传递给客户端组件,避免在客户端组件中调用useSearchParams()。
步骤1:修改页面组件,传递searchParams给<Pagination>
在页面的<Pagination>调用中新增searchParams属性:
// 页面组件中 <Pagination count={count} initialPage={parseInt(page)} searchParams={searchParams} // 传递服务器端拿到的searchParams />
步骤2:修改Pagination组件,使用传递的参数
移除useSearchParams()的依赖,改用父组件传递的参数:
'use client' import Link from "next/link"; import { useRouter } from "next/navigation"; // 移除useSearchParams导入 import { useEffect, useRef, useState } from "react"; type Props = { count: number initialPage: number searchParams: Record<string, string | string[]> // 新增参数类型 } export default function Pagination({ count, initialPage, searchParams }: Props) { // 将传入的searchParams转为URLSearchParams对象,保持原有用法 const pathParams = new URLSearchParams(searchParams) const isFirstRender = useRef(true) const maxPageLinks = 4; const [page, setPage] = useState(initialPage) const router = useRouter() const handleClick = (pageNum) => { setPage(pageNum); } useEffect(() => { if (isFirstRender.current) { isFirstRender.current = false return } const paramsStr = pathParams.toString() router.push(paramsStr ? `/page/${page}?${paramsStr}` : `/page/${page}`) }, [page, pathParams, router]) // 新增pathParams到依赖项 // getPages函数逻辑保持不变,因为pathParams对象用法和之前一致 const getPages = () => { let pages = []; const startPage = Math.max(page - Math.floor(maxPageLinks / 2), 1); const endPage = Math.min(startPage + maxPageLinks - 1, count); if (!pathParams) return [] if (count <= 5) { for (let i = 1; i <= count; i++) { pages.push( <Link href={`/page/${i}${pathParams.toString() ? `?${pathParams.toString()}` : ''}`} key={i} className={page === i ? 'active' : ''} onClick={() => handleClick(i)} > {i} </Link> ); } } else { if (startPage > 1) { pages.push( <Link href={`/page/1${pathParams.toString() ? `?${pathParams.toString()}` : ''}`} key={1} className={page === 1 ? 'active' : ''} onClick={() => handleClick(1)} > 1 </Link> ); if (startPage > 2) { pages.push(<div className="spread" key="spread-start">...</div>); } } for (let i = startPage; i <= endPage; i++) { pages.push( <Link href={`/page/${i}${pathParams.toString() ? `?${pathParams.toString()}` : ''}`} key={i} className={page === i ? 'active' : ''} onClick={() => handleClick(i)} > {i} </Link> ); } if (endPage < count) { if (endPage < count - 1) { pages.push(<div className="spread" key="spread-end">...</div>); } pages.push( <Link href={`/page/${count}${pathParams.toString() ? `?${pathParams.toString()}` : ''}`} key={count} className={page === count ? 'active' : ''} onClick={() => handleClick(count)} > {count} </Link> ); } } return pages; }; return ( <div className="pagination"> <div className={`previous ${page === 1 ? 'disabled' : ''}`} onClick={() => page > 1 && handleClick(page - 1)} > </div> {getPages()} <div className={`next ${page === count ? 'disabled' : ''}`} onClick={() => page < count ? handleClick(page + 1) : () => { }} > </div> </div> ); }
额外优化
当前<Link>已配置正确的href,点击Link本身即可触发路由跳转,handleClick配合useEffect的跳转逻辑属于冗余代码。如果仅需跳转功能,可直接移除这部分逻辑,简化组件;若需保留当前页码状态,可在客户端用usePathname和useSearchParams同步page值。
内容的提问来源于stack exchange,提问作者Hef
相关产品推荐
相关产品推荐

