问题的背景
HOC
在处理Next.Js页面时,一种常见的做法是使用HOC
(Higher-Order Component) 来避免重新键入页面的基础。
例如,身份验证HOC 可用于检查用户是否经过身份验证。根据结果,用户可以访问该页面或被重定向到登录页面。
布局
Next.Js程序员常用的另一种做法是Persistent Layouts
. 持久布局是页面上的一个“区域”,当用户浏览页面时不会重新呈现。这对 UX(用户体验)非常有用,例如,菜单的滚动位置保持在页面切换上。
一些不错的链接
CheatCode.co - 如何处理经过身份验证的路由(下面使用的 HOC)
问题
当结合这两种做法时,就会出现持久性问题。(阅读里面的评论AuthenticationRoute.js
这是一个非常简单的index.js
import authenticatedRoute from '@components/auth/AuthenticatedRoute';
const App = () => {
return (
<section>
<h1>Logged In</h1>
<h1>App</h1>
</section>
);
};
export default authenticatedRoute(App);
布局Layout.js
import Link from 'next/link';
import Navbar from '@components/layouts/Navbar';
import SideMenu from '@components/layouts/SideMenu';
function Layout({ children }) {
const baseUrl = '/app';
return (
<section>
<Navbar>
<li>
<Link href={`${baseUrl}/`}>Home</Link>
</li>
<li>
<Link href={`${baseUrl}/test1`}>Test 1</Link>
</li>
<li>
<Link href={`${baseUrl}/test2`}>Test 2</Link>
</li>
</Navbar>
<main>{children}</main>
</section>;
);
}
export default Layout;
最后是 HOCAuthenticationRoute.js
import { Component as component } from 'react';
import Router from 'next/router';
import Layout from '@components/layouts/app/Layout';
const authenticatedRoute = (Component = null, options = {}) => {
class AuthenticatedRoute extends component {
state = {
loading: true,
};
componentDidMount() {
const isSignedIn = true;
if (isSignedIn) {
this.setState({ loading: false });
} else {
Router.push(options.pathAfterFailure || '/sign_in');
}
}
render() {
const { loading } = this.state;
if (loading) {
return <div />;
}
// This will return the page without the layout
return <Component {...this.props} />;
// Removing the line above and using this instead
// the page now renders with the layout. BUT...
// The layout is not persistent, it will re-render
// everytime a user navigate.
const getLayout = (page) => <Layout>{page}</Layout>;
return getLayout(<Component {...this.props} />);
}
}
return AuthenticatedRoute;
};
export default authenticatedRoute;
没有 HOC
index.js
当不调用authenticatedRoute时,这在里面工作:
App.getLayout = getLayout;
export default App;
所以我的猜测是 authenticatedRoute 应该返回别的东西return <Component {...this.props} />;