NEXT JS - 如何防止重新安装布局?
NEXT JS - How to prevent layout get re-mounted?
下一步尝试布局模式:
https://github.com/zeit/next.js/tree/canary/examples/layout-component
问题是布局组件在每次页面更改时都会重新安装。我需要将布局组件用作容器,以便它在每次挂载时从服务器获取数据。如何防止重新安装布局?还是我遗漏了什么?
如果您将 Layout
组件放在页面组件内,它将在页面导航(页面切换)时重新挂载。
您可以将您的页面组件与 Layout
组件包裹在 _app.js
内,这样可以防止它重新加载。
像这样:
// _app.js
import Layout from '../components/Layout';
class MyApp extends App {
static async getInitialProps(appContext) {
const appProps = await App.getInitialProps(appContext);
return {
...appProps,
};
}
render() {
const { Component, pageProps } = this.props;
return (
<Layout>
<Component {...pageProps} />
<Layout />
);
}
}
export default MyApp;
这对持久布局很有帮助。作者将一个函数放在一起,将您的页面组件包装在您的 Layout 组件中,然后将该获取函数传递给您的 _app.js。这样 _app.js 实际上是呈现布局的组件,但您可以指定哪些页面使用哪种布局(如果您有多个布局)。
因此您可以灵活地在整个站点中使用多个布局,但共享相同布局的那些页面实际上将共享相同的布局组件,并且不必在导航时重新安装它。
这里是 link 全文
Persistent Layout Patterns in Next.js
这是重要的代码片段。一个页面然后 _app.js
// /pages/account-settings/basic-information.js
import SiteLayout from '../../components/SiteLayout'
import AccountSettingsLayout from '../../components/AccountSettingsLayout'
const AccountSettingsBasicInformation = () => (
<div>{/* ... */}</div>
)
AccountSettingsBasicInformation.getLayout = page => (
<SiteLayout>
<AccountSettingsLayout>{page}</AccountSettingsLayout>
</SiteLayout>
)
export default AccountSettingsBasicInformation
// /pages/_app.js
import React from 'react'
import App from 'next/app'
class MyApp extends App {
render() {
const { Component, pageProps, router } = this.props
const getLayout = Component.getLayout || (page => page)
return getLayout(<Component {...pageProps}></Component>)
}
}
export default MyApp
即使这是主题 Layout
被一次又一次地挂载,这个问题的根本原因是您在某个子组件中加载了一些数据,这些数据被一次又一次地获取。
经过一番折腾,我发现none这些问题实际上是Next.Js或SWR解决的问题。回到第一个问题,如何将单个数据副本简化为某个子组件。
上下文
以context
为例。
Config.js
import { createContext } from 'react'
export default createContext({})
_App.js
import Config from '../Config'
export default function App({ Component, pageProps }) {
return (
<Config.Provider value={{ user: { name: 'John' }}}>
<Component {...pageProps} />
</Config.Provider>
)
}
Avatar.js
import { useContext } from 'react'
import Config from '../Config'
function Avatar() {
const { user } = useContext(Config)
return (
<span>
{user.name}
</span>
)
}
export default Avatar
无论您如何装载和卸载,只要 _app
没有,您就不会重新渲染。
可写
上面的例子只是处理可读的。如果它是可写的,您可以尝试将状态传递到上下文中。 setUser
将负责消费者中的设置。
<Provider value={useState({})} />
const [user, setUser] = useContext(Config)
setUser
已“缓存”,不会更新。所以我们可以使用这个函数在子消费者中随时重置用户。
还有其他方法,例如。反应反冲。但或多或少,您正在处理一个状态管理系统,以便在不接触其他节点的情况下将副本(值或函数)发送到其他地方。我会留下这个作为答案,因为即使我们解决了布局问题,这个问题也不会消失。而如果我们解决了这个问题,我们就根本不需要处理Layout
此外,请确保将所有 <a href=""></a>
替换为 <Link href=""></Link>
,注意仅将 Html 标记更改为 link。
我为此苦苦挣扎了很多天,虽然我做的其他一切都正确,但这些 <a>
标签是导致 _app.js
在页面更改时重新加载的罪魁祸首
下一步尝试布局模式:
https://github.com/zeit/next.js/tree/canary/examples/layout-component
问题是布局组件在每次页面更改时都会重新安装。我需要将布局组件用作容器,以便它在每次挂载时从服务器获取数据。如何防止重新安装布局?还是我遗漏了什么?
如果您将 Layout
组件放在页面组件内,它将在页面导航(页面切换)时重新挂载。
您可以将您的页面组件与 Layout
组件包裹在 _app.js
内,这样可以防止它重新加载。
像这样:
// _app.js
import Layout from '../components/Layout';
class MyApp extends App {
static async getInitialProps(appContext) {
const appProps = await App.getInitialProps(appContext);
return {
...appProps,
};
}
render() {
const { Component, pageProps } = this.props;
return (
<Layout>
<Component {...pageProps} />
<Layout />
);
}
}
export default MyApp;
这对持久布局很有帮助。作者将一个函数放在一起,将您的页面组件包装在您的 Layout 组件中,然后将该获取函数传递给您的 _app.js。这样 _app.js 实际上是呈现布局的组件,但您可以指定哪些页面使用哪种布局(如果您有多个布局)。
因此您可以灵活地在整个站点中使用多个布局,但共享相同布局的那些页面实际上将共享相同的布局组件,并且不必在导航时重新安装它。
这里是 link 全文 Persistent Layout Patterns in Next.js
这是重要的代码片段。一个页面然后 _app.js
// /pages/account-settings/basic-information.js
import SiteLayout from '../../components/SiteLayout'
import AccountSettingsLayout from '../../components/AccountSettingsLayout'
const AccountSettingsBasicInformation = () => (
<div>{/* ... */}</div>
)
AccountSettingsBasicInformation.getLayout = page => (
<SiteLayout>
<AccountSettingsLayout>{page}</AccountSettingsLayout>
</SiteLayout>
)
export default AccountSettingsBasicInformation
// /pages/_app.js
import React from 'react'
import App from 'next/app'
class MyApp extends App {
render() {
const { Component, pageProps, router } = this.props
const getLayout = Component.getLayout || (page => page)
return getLayout(<Component {...pageProps}></Component>)
}
}
export default MyApp
即使这是主题 Layout
被一次又一次地挂载,这个问题的根本原因是您在某个子组件中加载了一些数据,这些数据被一次又一次地获取。
经过一番折腾,我发现none这些问题实际上是Next.Js或SWR解决的问题。回到第一个问题,如何将单个数据副本简化为某个子组件。
上下文
以context
为例。
Config.js
import { createContext } from 'react'
export default createContext({})
_App.js
import Config from '../Config'
export default function App({ Component, pageProps }) {
return (
<Config.Provider value={{ user: { name: 'John' }}}>
<Component {...pageProps} />
</Config.Provider>
)
}
Avatar.js
import { useContext } from 'react'
import Config from '../Config'
function Avatar() {
const { user } = useContext(Config)
return (
<span>
{user.name}
</span>
)
}
export default Avatar
无论您如何装载和卸载,只要 _app
没有,您就不会重新渲染。
可写
上面的例子只是处理可读的。如果它是可写的,您可以尝试将状态传递到上下文中。 setUser
将负责消费者中的设置。
<Provider value={useState({})} />
const [user, setUser] = useContext(Config)
setUser
已“缓存”,不会更新。所以我们可以使用这个函数在子消费者中随时重置用户。
还有其他方法,例如。反应反冲。但或多或少,您正在处理一个状态管理系统,以便在不接触其他节点的情况下将副本(值或函数)发送到其他地方。我会留下这个作为答案,因为即使我们解决了布局问题,这个问题也不会消失。而如果我们解决了这个问题,我们就根本不需要处理Layout
此外,请确保将所有 <a href=""></a>
替换为 <Link href=""></Link>
,注意仅将 Html 标记更改为 link。
我为此苦苦挣扎了很多天,虽然我做的其他一切都正确,但这些 <a>
标签是导致 _app.js
在页面更改时重新加载的罪魁祸首