Next.js: Fast Refresh Full Reload warning is incomplete (and partly unclear)

Created on 18 May 2020  路  3Comments  路  Source: vercel/next.js

Bug report

Describe the bug

Fast Refresh does not support unnamed function components (closed issue), yet the warning provided does not mention this.

To Reproduce

pages/index.js:

import '../src/somefile'

export default () => null;

Then edit and save somefile.

Works

import '../src/somefile'

const Page = () => null;

export default Page;

Expected behavior

The warning should mention that Fast Refresh does not support unnamed function components.

System information

  • Version of Next.js: 9.4.1

Additional context

I know that the warning was only introduced in 9.4.1 (and is a huge improvement on the error in 9.4.0), so it will most likely be subject to near future iterations. Here's how I read it:

Fast Refresh will perform a full reload when you edit a file that's imported by modules outside of the React tree.

Probably my ignorance, but I was a bit confused about what "modules outside of the React tree" mean here. Does this mean the React components tree? Is somefile outside of the react tree? I mean, there is a dependency graph, but it is not a tree.

You might have a file which renders a React component but also exports a value that is imported by a non-React component.

First, files don't 'render' a React component - files 'export' react components.

I don't really understand whether this is said within the context of the whole dependency graph or what? Does this mean that if I have a file that exports a react component, but also some function (or a type like Props) that is then imported in a test, that will break Fast Refresh

Consider migrating the non-React component export to a separate file and importing it into both files.

What's a "non-React component`? An angular one?

It is also possible you are using class components at the top-level of your application, which disables Fast Refresh.

This is also unclear. What constitutes the "top-level of your application"? Some options:

  • A page's default export
  • pages/_app.js
  • pages/_document.js

Fast Refresh requires at least one function component in your React tree.

That is clear and the reproduction case above comply with this.

Anyhow, while there is a place for improvement in my view to other parts of the warning, I believe my issue would be solved if the last line would say:

Fast Refresh requires at least one _named_ function component in your React tree.

Yet I'm not sure this is correct. Is it any odd function component that needs to be named, or the one exported from a page?

story documentation

Most helpful comment

I'm not sure if this is possible, but if the page is doing a full reload, is there a way to figure out which file is causing it? I have tried all the optimizations from the readme on my home page, and I can't for the life of me figure out what is causing a full reload. Fast refresh works fine on other pages. Is there a way to give a warning that says which file caused the reload?

Thanks!

All 3 comments

Another gotcha below.

While improvements are due in 9.4.2, the code doesn't reveal much. Any chance to provide some simple explanation as for why Full Reload happens? The linked code is HMR, and you didn't get Full Reloads before Fast Refresh, so where should one look in the code to figure this thing out?

Full Reload

export default withTests(suite)(TestTree);

Although they are all named:

image

import React from 'react';
import { Provider } from 'react-redux';
import withNoSSR from './withNoSSR';

export default (suite) => (WrappedComponent) => {
  const { store } = suite;
  const withTests = (props) => (
    <Provider store={store}>
      <WrappedComponent {...props} />
    </Provider>
  );

  return withNoSSR(withTests);
};

No Full Reload

const Tree = withTests(suite)(TestTree);

const Page = () => <Tree />;

export default Page;

Although I know little about HMR, I have some hunch that the rule is this:

You page must export a named component that is defined in the page script itself.

You will not get full reload so long your page exports like this:

const Page = () => ( /* Whatever */ );

export default Page;

Or equally:

export default function Page() {
  return ( /* Whatever */ )
}

Is that correct?

I'm not sure if this is possible, but if the page is doing a full reload, is there a way to figure out which file is causing it? I have tried all the optimizations from the readme on my home page, and I can't for the life of me figure out what is causing a full reload. Fast refresh works fine on other pages. Is there a way to give a warning that says which file caused the reload?

Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sospedra picture sospedra  路  3Comments

havefive picture havefive  路  3Comments

irrigator picture irrigator  路  3Comments

flybayer picture flybayer  路  3Comments

formula349 picture formula349  路  3Comments