如何在不重新加载整个页面的情况下重新加载Next.js页面的初始道具

时间:2020-05-18 16:13:19

标签: javascript next.js

我有一个Next.js页面,该页面在getInitialProps函数中获取数据,我想从浏览器重新加载此数据而不重新加载该页面,这会导致性能下降并失去用户的滚动位置。有什么方法可以在不重新加载整个页面的情况下重新加载初始道具吗?

2 个答案:

答案 0 :(得分:1)

这可以通过调用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。因此,就像在客户端重定向到同一页面一样,客户端重定向会重新获取道具。

我不相信上面的答案是行不通的,因为不能将功能序列化并从服务器发送到客户端。

答案 1 :(得分:0)

您可以使用将最后的初始道具存储为状态的高阶组件,并可以通过调用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);