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

Next.js实现无刷新更新新闻页URL并兼容浏览器历史按钮

解决方案:Next.js 无刷新更新分类URL+保持前进后退正常

核心思路

用Next.js官方的动态路由 + 客户端路由导航 + 路由变化监听,既实现URL的路径式分类,又不刷新页面,同时保证浏览器前进后退能同步更新内容。


针对 Pages Router(Next.js 12及更早)

1. 先配置动态路由

在pages/news目录下创建category/[slug].js文件,复用原/news页面的逻辑,或者把新闻列表抽成可复用组件避免重复代码:

// pages/news/category/[slug].js
import NewsList from '../../components/NewsList';
import { useRouter } from 'next/router';

export default function NewsCategory() {
  const router = useRouter();
  const { slug } = router.query; // 当前分类,比如entertainment

  return <NewsList category={slug} />;
}

2. 客户端无刷新导航

在原/news页面的分类按钮点击事件里,用router.push配合shallow: true(注意:必须是同一页面组件内的路由变化,shallow才会生效,这是你之前方案1失效的关键):

// pages/news/index.js
import { useRouter } from 'next/router';

export default function NewsPage() {
  const router = useRouter();

  const handleCategoryChange = (category) => {
    const targetUrl = `/news/category/${category}`;
    router.push(targetUrl, undefined, { shallow: true });
  };

  return (
    <div>
      <button onClick={() => handleCategoryChange('entertainment')}>娱乐</button>
      <button onClick={() => handleCategoryChange('technology')}>科技</button>
      <NewsList category={router.query.slug || 'all'} />
    </div>
  );
}

3. 监听路由变化更新列表

在NewsList组件里,监听router.query的变化,自动发起API请求更新内容:

// components/NewsList.js
import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';

export default function NewsList({ category }) {
  const [articles, setArticles] = useState([]);
  const router = useRouter();

  useEffect(() => {
    const fetchArticles = async () => {
      const res = await fetch(`/api/news?category=${category}`);
      const data = await res.json();
      setArticles(data);
    };

    fetchArticles();
  }, [category]); // 分类变化时触发请求

  return (
    <div className="articles">
      {articles.map(article => (
        <div key={article.id}>{article.title}</div>
      ))}
    </div>
  );
}

针对 App Router(Next.js 13+)

1. 配置动态路由

在app/news目录下创建category/[slug]/page.js:

// app/news/category/[slug]/page.js
import NewsList from '../../components/NewsList';

export default function NewsCategoryPage({ params }) {
  const { slug } = params; // 当前分类

  return <NewsList category={slug} />;
}

2. 客户端无刷新导航

在app/news/page.js里用useRouter(来自next/navigation)做导航:

// app/news/page.js
'use client'; // 必须标记为客户端组件才能用useRouter

import { useRouter } from 'next/navigation';
import NewsList from './components/NewsList';

export default function NewsPage() {
  const router = useRouter();

  const handleCategoryChange = (category) => {
    router.push(`/news/category/${category}`);
    // App Router默认就是客户端无刷新导航,无需额外配置
  };

  return (
    <div>
      <button onClick={() => handleCategoryChange('entertainment')}>娱乐</button>
      <button onClick={() => handleCategoryChange('technology')}>科技</button>
      <NewsList category="all" />
    </div>
  );
}

3. 监听路由变化更新列表

在NewsList组件里,用usePathname监听路径变化,自动更新内容:

// app/news/components/NewsList.js
'use client';

import { useEffect, useState } from 'react';
import { usePathname } from 'next/navigation';

export default function NewsList({ category }) {
  const [articles, setArticles] = useState([]);
  const pathname = usePathname();

  useEffect(() => {
    const currentCategory = category || pathname.split('/').pop();
    const fetchArticles = async () => {
      const res = await fetch(`/api/news?category=${currentCategory}`);
      const data = await res.json();
      setArticles(data);
    };

    fetchArticles();
  }, [pathname, category]); // 路径或分类变化时触发请求

  return (
    <div className="articles">
      {articles.map(article => (
        <div key={article.id}>{article.title}</div>
      ))}
    </div>
  );
}

为什么之前的方案失效?

  • 方案1:未配置对应的动态路由,导致shallow: true无法生效(shallow路由要求目标URL对应同一个页面组件),触发了全页面刷新。
  • 方案2:直接用原生history API绕开了Next.js的路由系统,Next.js无法监听路由变化,所以前进后退时不会更新页面内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 02:28:25