React.memo for page components
When using React.memo as the exported component in a page, Next JS throws an error :
The default export is not a React Component in page: "/"
You can check the behaviour here :
https://codesandbox.io/s/k2jx562o3
The memo component should be considered a valid component

When adding memo to the component while hot reloading is active, it doesn't throw the error.
In that case, the error occurs only on first load, or when we reload the page.
Probably because of this line
https://github.com/zeit/next.js/blob/b63dda7cf7e9a58c3687fb8007c1d899b692584d/packages/next-server/server/render.js#L86
Switching to react-is would probably solve it and make this condition future-proof
I was just writing the same issues !
I faced same identical problem using no other than the code in the learn section.
I am surprised becaused I've written the 'learn' section code about ten times and it's the first time I got this problem.
import withLayout from '../lib/layout'
const Page = () => (
<p>This is the HOME page</p>
)
export default withLayout(Page)
import Header from '../components/header'
const layoutStyle = {
margin: 20,
padding: 20,
border: '1px solid #DDD'
}
const Layout = (props) => (
<div style={layoutStyle}>
<Header />
{props.children}
</div>
)
export default Layout
The default export is not a React Component in page: "/index"
Error: The default export is not a React Component in page: "/index"
at _callee3$ (E:\next_js\agenda\node_modules\next\dist\server\render.js:242:19)
at tryCatch (E:\next_js\agenda\node_modules\regenerator-runtime\runtime.js:62:40)
at Generator.invoke [as _invoke] (E:\next_js\agenda\node_modules\regenerator-runtime\runtime.js:288:22)
at Generator.prototype.(anonymous function) [as next] (E:\next_js\agenda\node_modules\regenerator-runtime\runtime.js:114:21)
at asyncGeneratorStep (E:\next_js\agenda\node_modules\@babel\runtime-corejs2\helpers\asyncToGenerator.js:5:24)
at _next (E:\next_js\agenda\node_modules\@babel\runtime-corejs2\helpers\asyncToGenerator.js:27:9)
NOTE: if I remove withLayout() wrapping, the index.js pages work well again
IF usefull...
{
"scripts": {
"dev": "cross-env DEBUG=* node server.js",
"build": "next build",
"start": "cross-env NODE_ENV=production node server.js"
},
"dependencies": {
"@zeit/next-sass": "^1.0.1",
"express": "^4.16.4",
"next": "^7.0.2",
"next-compose": "0.0.2",
"node-sass": "^4.10.0",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"workbox-webpack-plugin": "^3.6.3"
},
"devDependencies": {}
}
To investigate, I added a console.log in the code of next/dist/server/render.js
case 9:
_ref3 = _context3.sent;
_ref4 = (0, _slicedToArray2.default)(_ref3, 5);
buildManifest = _ref4[0];
reactLoadableManifest = _ref4[1];
Component = _ref4[2];
Document = _ref4[3];
App = _ref4[4];
Component = Component.default || Component;
console.log(Component); // <<------- I added this
if (!(typeof Component !== 'function')) {
_context3.next = 19;
break;
}
throw new Error("The default export is not a React Component in page: \"".concat(page, "\""));
This is what I got
{ '$$typeof': Symbol(react.element),
type: 'div',
key: null,
ref: null,
props:
{ style: { margin: 20, padding: 20, border: '1px solid #DDD' },
children: [ [Object], undefined ] },
_owner: null,
_store: {} }
Error: The default export is not a React Component in page: "/index"
at _callee3$ (E:\next_js\agenda\node_modules\next\dist\server\render.js:244:21)
at tryCatch (E:\next_js\agenda\node_modules\regenerator-runtime\runtime.js:62:40)
at Generator.invoke [as _invoke] (E:\next_js\agenda\node_modules\regenerator-runtime\runtime.js:288:22)
at Generator.prototype.(anonymous function) [as next] (E:\next_js\agenda\node_modules\regenerator-runtime\runtime.js:114:21)
at asyncGeneratorStep (E:\next_js\agenda\node_modules\@babel\runtime-corejs2\helpers\asyncToGenerator.js:5:24)
at _next (E:\next_js\agenda\node_modules\@babel\runtime-corejs2\helpers\asyncToGenerator.js:27:9)
at process._tickCallback (internal/process/next_tick.js:68:7)
I hope someone could understand something, I'm not able to follow the reasoning that the renderer is doing in evaluating the component, sorry.
@realtebo in your case the issue is you are returning the React element, not a React component.
Change your lib/layout.js to
import Header from '../components/header'
const layoutStyle = {
margin: 20,
padding: 20,
border: '1px solid #DDD'
}
const withLayout = Component => (props) => (
<div style={layoutStyle}>
<Header />
<Component />
</div>
)
export default withLayout
Or something like that. what's happening is your are using a normal component as a High Order Component, the correct syntax of a HOC is WrappedComponent => NewComponent where your NextComponent (in your case is withLayout) can use the WrappedComponent (your page) internally.
@sergiodxa : _mine_ is the suggested code here: https://nextjs.org/learn/basics/using-shared-components/the-layout-component
I don't know why _now_ it not works; it worked until yesterday. Sorry that this doesn't help.
I changed index.js and about.js to follow the suggested schema
// pages/index.js
import Layout from '../components/MyLayout.js'
export default () => (
<Layout>
<p>Hello Next.js</p>
</Layout>
)
Now it works. So thanks @sergiodxa
PR here: #5095, it's a little outdated though
@realtebo if you check the page, you are using the layout as a HOC doing withLayout(Page) but the tutorial is using as a normal component.
import Layout from '../components/MyLayout.js'
export default () => (
<Layout>
<p>This is the about page</p>
</Layout>
)
It just render Layout as a component wrapping the rest of the page. You can either use it that way or as a HOC, in the case of a HOC you need to follow the WrappedComponent => NewComponent syntax.
Thanks for the super detailed issue including codesandbox reproduction 馃挴馃檹 Let's track this issue in #4055
Most helpful comment
@realtebo in your case the issue is you are returning the React element, not a React component.
Change your
lib/layout.jstoOr something like that. what's happening is your are using a normal component as a High Order Component, the correct syntax of a HOC is
WrappedComponent => NewComponentwhere yourNextComponent(in your case iswithLayout) can use the WrappedComponent (your page) internally.