You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next13 App Router报错:类型'AppRouterInstance'不存在'query'属性

问题分析

Next.js 13 App Router 中,从 next/navigation 导入的 useRouter 和旧版 Pages Router 的 useRouter 完全不同——前者没有 query 属性,所以你写 const { query } = router 必然触发类型错误。

解决方案

方法1:客户端组件用 useParams 取动态参数

你的页面加了 'use client' 标记属于客户端组件,直接用 Next.js 提供的 useParams 钩子就能拿到动态路由里的 id:

  1. 导入 useParams:
import { useParams } from 'next/navigation';
  1. 替换原路由相关代码:
// 删除这两行:
// const router = useRouter();
// const { query } = router;

// 替换为:
const params = useParams();
const id = params.id as string; // useParams返回值为string | string[],需断言为string类型

修改后的完整客户端组件代码:

'use client';

import { useParams } from 'next/navigation';
import { useEffect } from 'react';
import data from '../../../data.json';
import React from 'react';

export default function Work() {
    const params = useParams();
    const id = params.id as string;
  
    useEffect(() => {
      console.log(data.portfolioData);
    }, []);
  
    const item = data.portfolioData.find((item) => item.id.toString() === id);
  
    if (!item) {
      return <div>Loading...</div>;
    }
  
  return (
    <main className="min-h-screen bg-secondary">
      <section>
        <div
          style={{
            backgroundImage: `url("/images/text-bg.png")`,
            backgroundSize: 'cover',
            backgroundPosition: 'center',
            backgroundRepeat: 'no-repeat',
          }}
        ></div>
      </section>
      <div className="xl:container mx-auto px-4 sm:px-6 xl:px-0">
        <h1 className="mt-12 text-3xl font-bold font-termina text-primary mb-6 text-center sm:text-left">
          <span className="font-light">MY</span> <br />DESIGNS
        </h1>

        <div className="bg-accent p-4 card">
          {/* 这里建议渲染单个匹配的item详情,原代码遍历所有数据是错误的 */}
          <div className="rounded-lg w-auto bg-accent relative transform hover:scale-105 hover:rotate-1 transition-all duration-500 shadow-2xl">
            <img className="rounded-lg" src={item.thumbnail} alt={item.title} />
            <div className="rounded-lg absolute inset-0 flex flex-col items-center justify-center opacity-0 hover:opacity-100 transition-opacity duration-500 bg-black bg-opacity-70">
              <h3 className="text-md font-termina font-semibold text-white">{item.title}</h3>
            </div>
          </div>
        </div>
      </div>
    </main>
  );
}

方法2:改成服务器组件(更推荐)

如果页面不需要客户端交互,可去掉 'use client' 标记,直接在服务器组件中接收 params 参数——这是 App Router 最佳实践,性能更优:

// 移除'use client',转为服务器组件
import data from '../../../data.json';

// 直接从组件参数获取动态路由params
export default function Work({ params }: { params: { id: string } }) {
    const item = data.portfolioData.find((item) => item.id.toString() === params.id);
  
    if (!item) {
      return <div>Loading...</div>;
    }
  
  return (
    <main className="min-h-screen bg-secondary">
      <section>
        <div
          style={{
            backgroundImage: `url("/images/text-bg.png")`,
            backgroundSize: 'cover',
            backgroundPosition: 'center',
            backgroundRepeat: 'no-repeat',
          }}
        ></div>
      </section>
      <div className="xl:container mx-auto px-4 sm:px-6 xl:px-0">
        <h1 className="mt-12 text-3xl font-bold font-termina text-primary mb-6 text-center sm:text-left">
          <span className="font-light">MY</span> <br />DESIGNS
        </h1>

        <div className="bg-accent p-4 card">
          <div className="rounded-lg w-auto bg-accent relative transform hover:scale-105 hover:rotate-1 transition-all duration-500 shadow-2xl">
            <img className="rounded-lg" src={item.thumbnail} alt={item.title} />
            <div className="rounded-lg absolute inset-0 flex flex-col items-center justify-center opacity-0 hover:opacity-100 transition-opacity duration-500 bg-black bg-opacity-70">
              <h3 className="text-md font-termina font-semibold text-white">{item.title}</h3>
            </div>
          </div>
        </div>
      </div>
    </main>
  );
}

注意:若页面需要客户端交互(如点击事件、状态管理),再用客户端组件方案;否则优先用服务器组件,无需导入路由钩子,代码更简洁,还能在服务器端完成数据匹配,减少客户端计算。

内容的提问来源于stack exchange,提问作者Chris Barnett

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 10:24:55