我有一个 Next.js 页面,在 getInitialProps
函数中获取数据,我想在不重新加载页面的情况下从浏览器重新加载这些数据,因为重新加载会影响性能并且会丢失用户的滚动位置。是否有一种方法可以重新加载初始属性而不重新加载整个页面?
我有一个 Next.js 页面,在 getInitialProps
函数中获取数据,我想在不重新加载页面的情况下从浏览器重新加载这些数据,因为重新加载会影响性能并且会丢失用户的滚动位置。是否有一种方法可以重新加载初始属性而不重新加载整个页面?
可以通过调用router.replace
来实现:
import { useRouter } from 'next/router';
function YourPage({ someProps }) {
const router = useRouter();
// Call this function when you want to refresh the data
const refreshData = () => router.replace(router.asPath);
// Your JSX
}
router.replace
是一种更新 URL 而不会在历史记录中新增条目的方法。router.asPath
表示当前的 URL。因此这就像是对同一页进行客户端重定向,而客户端重定向将重新获取 props。
上述答案不可行,因为函数无法从服务器序列化并发送到客户端。
getInitialProps
并将状态设置为其返回值来重新加载它们。以下是一个可以实现此功能的HOC:import { NextPage, NextPageContext } from 'next';
import React, { useState, PropsWithChildren, ComponentType } from 'react';
/**
* Removes never-used context values to reduce bloat. Context values may come from server but then
* be used client-side because they are saved in initial props.
*/
function minifyContext(context) {
return { ...context, req: undefined, res: undefined };
}
const withSoftReload = Page => {
async function getInitialProps(ctx) {
return { context: minifyContext(ctx), ...(await Page.getInitialProps(ctx)) };
}
const omitContextFromProps = ({
context,
...props
}) => props;
const NewPage = props => {
// set inner page initial props to wrapper initial props minus context
const [initialProps, setInitialProps] = useState(omitContextFromProps(props));
async function softReload() {
setInitialProps({ children: null, ...(await Page.getInitialProps(props.context)) });
}
return (
<Page
{...{ ...initialProps, softReload }}
/>
);
};
NewPage.getInitialProps = getInitialProps;
NewPage.displayName = `withSoftReload(${Page.displayName})`;
return NewPage;
};
export default withSoftReload;
const MyPage = ({ data, softReload }) => (
<div>
{data}
<button onClick={softReload}>Refresh</button>
</div>
);
MyPage.getInitialProps = async (ctx) => {
// fetch data
};
export default withSoftReload(MyPage);