在Next.js中触发客户端重新加载页面。

32

场景

索引页面使用“getInitialProps”加载数据。然后我们创建一个对话框,可以创建新的数据。创建完新数据后,应该重新加载当前页面。

问题

我们使用Router.replace('/')重新加载页面。但这会触发服务器端渲染。

问题

我们需要的是客户端重新加载。"getInitialProps"函数应该在浏览器中被调用。那么,如何进行客户端重新加载?


你可以使用这个方便的模块 https://github.com/shdnx/next-express - lakshman.pasala
我们现在正在使用纯粹的Next.js,还没有引入Express。 - Jim Jin
getInitialProps 只能在服务器端渲染时调用,您可以在客户端上始终调用 componentDidMount - Agney
6
可以。"getInitialProps" 可以在客户端被调用。 - Jim Jin
8个回答

29
假设用户在 http://www.example.com/profile 页面上编辑了个人资料,并出于某种原因,您需要重新加载相同的页面。如果您的情况类似于此,则可以使用 Router.reload(); 方法。请记住,您必须像这样导入 Router 对象: import Router from "next/router";。更多信息请参见:https://nextjs.org/docs/api-reference/next/router#routerreload

22
更好的选择是使用router.replace(router.asPath) replace不会创建新的历史记录,因此返回按钮可以按预期工作。
详细信息请参见本文https://www.joshwcomeau.com/nextjs/refreshing-server-side-props/
import { useRouter } from "next/navigation";

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

  router.replace(router.asPath);
}

7
谢谢。虽然我认为 router.asPath 应该是 router.replace() 的默认参数。 - Jim Jin
2
只有我一个人还是AS路径不存在? - David
@David,它确实存在于路由器对象上 https://nextjs.org/docs/api-reference/next/router - Amit

14

从NextJs 13版本开始,新的路由对象具有refresh()方法,它允许您在客户端刷新(重新获取)数据而无需进行完整的页面重新加载。

可以像以下方式使用:

import { useRouter } from "next/navigation";

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

  //this will reload the page without doing SSR
  router.refresh();
}


请记住,这是 Next.js 13 的一个功能,目前处于测试版。
在此处查看 beta 文档:https://beta.nextjs.org/docs/api-reference/use-router 感谢 Fireship 展示该功能。
https://www.youtube.com/watch?v=__mSgDEOyv8

6
接下来的13个路由器不再属于“next/router”模块,而是改为属于“next/navigation”模块。建议你稍微修改一下你的代码以避免误解和错误。更多信息请参见:https://beta.nextjs.org/docs/routing/linking-and-navigating#userouter-hook - Marcos R
似乎无法通过Prisma使刷新工作 - 因为它不遵循获取模式。 - Dylan Cronkhite
这感觉像是来自next/router的router.reload(),也就是说,像一个初始请求 - 在服务器上真正重新创建页面并由浏览器加载响应 - 非常慢。使用router.replace(router.asPath)似乎只重新获取页面属性并根据需要替换更改的DOM分支 - 速度更快。 - jelmd

13

没有看到真正符合我需求的答案,

这个对我有用:

import Router from 'next/router'

Router.reload(window.location.pathname);

18
Router.reload() 等同于 window.location.reload(),不应该向其传递网址。 - Sajad Saderi

2
运行以下代码:

pages/index.js

import Router from 'next/router';

function Index({ isServer }) {
  console.log('render', new Date());

  return (
    <div>
      <h1>Home page. Is it on server? - {isServer ? 'Yes' : 'No'}</h1>

      <button type="button" onClick={() => Router.push('/')}>
        Reload me
      </button>
    </div>
  );
}

Index.getInitialProps = async ({ req }) => {
  return { isServer: !!req };
};

export default Index;

我看到在服务器上点击“Reload me”后,它只会在渲染时使用console.log一次。我还可以看到,在“reload”后,isServer也等于false。
您如何确切地重新加载页面,以便您可以在服务器端看到它已呈现?
PS
以下是截图:

1
感谢您的回复。我发现在我的本地环境中,Router.replace('/')(客户端渲染)可以正常工作。然而,在生产环境中,它会触发服务器端渲染。我可以在浏览器的调试窗口中看到网络访问。本地环境和生产环境之间唯一的区别是生产环境中有nginx和资源前缀。这非常奇怪。 - Jim Jin
不,我不自定义 server.js。 - Jim Jin
这是重现步骤:“https://locationbackbone.top/scenariobus/”,用户名:“testbus@bytebilling.com”,密码:“qwe!@#123”。这是一个沙盒环境,所以请随意测试。 - Jim Jin
第三种情况,在登录后,只需点击左上角的“公交”图标,服务器渲染。在我的本地笔记本电脑上,客户端渲染。 - Jim Jin
2
确认了!设置资产前缀会导致这个错误。已经向Next.js开放了一个问题。 - Jim Jin
显示剩余10条评论

2
如果你正在使用AppRouter并且需要强制刷新,你可以使用以下代码。
router.push(window.location.href);
router.refresh();

只使用router.refresh();可以吗? - Jim Jin
只有 router.refresh() 在我的端上没有起作用。 - Devdreamsolution
router.push(window.location.href);是否会触发服务器负载? - Jim Jin
我猜这只是推动或者你可以使用替换。 - undefined
我觉得这只是推动或者你可以使用替换。 - Devdreamsolution
显示剩余2条评论

1
如果你想在Next.js版本13中在客户端刷新页面,只需使用window.location.reload()

使用Next.js 14,这是我能够执行完整页面重新加载的唯一方法。 - undefined

1

如果你正在使用nextjs Link,它会预加载页面。如果你需要默认的重新加载,你需要使用一个标签而不是Link。


虽然这已经被解释给我了,但我仍然使用了一个链接来更改语言。将其切换为锚标签确保页面重新加载并更改翻译! - HotFix
尽管这已经向我解释过了,但我仍然使用了一个链接来更改语言。将其切换为锚标签确保页面重新加载并更改了翻译! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接