最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to reload Next.js page initial props without reloading the whole page - Stack Overflow

programmeradmin1浏览0评论

I have a Next.js page that fetches data in the getInitialProps function and I want to reload this data from the browser without reloading the page, which would be unperformant and lose the user's scroll position. Is there some way to reload the initial props without reloading the entire page?

I have a Next.js page that fetches data in the getInitialProps function and I want to reload this data from the browser without reloading the page, which would be unperformant and lose the user's scroll position. Is there some way to reload the initial props without reloading the entire page?

Share Improve this question asked May 18, 2020 at 16:13 Robert MooreRobert Moore 2,5724 gold badges25 silver badges48 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 17

This can be done by calling 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 is a method to update the URL without adding a new entry to the history. router.asPath is the current URL. So it's like doing a client-side redirect to the same page, and client-side redirects re-fetch the props.

The answer above won't work, I don't believe, since functions can't be serialized and sent from server to client.

You could use a higher order component that stores the last initial props as state and can reload those by calling getInitialProps and setting the state to its return value. Here's a HOC that would do that:

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;

In your pages you would use it like this:

const MyPage = ({ data, softReload }) => (
  <div>
    {data}
    <button onClick={softReload}>Refresh</button>
  </div>
);

MyPage.getInitialProps = async (ctx) => {
  // fetch data
};

export default withSoftReload(MyPage);
发布评论

评论列表(0)

  1. 暂无评论