【发布时间】:2021-05-23 22:51:19
【问题描述】:
我有一个 header.js 组件,它出现在我的 next.js/react 项目的每个页面上。
在里面我创建了一个带有旋转的打字机效果,所以为了启动它,我将代码放在 useEffect 中:
export default function Header () {
useEffect(() => {
let delay = 2200;
let input = document.getElementsByClassName('myButton')[0],
index = 0;
const cycleText = () =>{
let randomItem = items[Math.floor(Math.random() * items.length)];
button.setAttribute('value', "Click " + randomItem);
index++;
(index === items.length) ? index = 0 : "";
setTimeout(cycleText, delay);
}
cycleText();
}, []);
return ( ...
要像使用 jQuery 一样重新创建 document.ready,尽管我在使用 useEffect 时遇到了两个问题,一个是如果我更改页面,标题保持不变,但效果代码看起来死了(不再显示文本),二,如果我回到主页,代码在第一次加载时工作正常,现在它显示了两个快速成功的旋转实例(好像有两个 useEffect 在同时一个在另一个之上,或类似的东西)。
我越来越了解 useEffect 的工作原理,我知道 [] 使它在页面加载时运行一次,但我认为这就是我的情况所需要的,而且看起来我错了。我应该在 [] 中传递一些可以解决上述两个问题的东西吗?我尝试使用 next.js 路由器,传递 router.pathname,让它在每次页面更改时再次运行,但不起作用。
更新:我注意到上面描述的两个奇怪的行为只发生在从主页到预先生成的页面(通过 staticPaths 和 staticProps)并返回时。 如果我从主页转到用户仪表板(服务器端呈现)并返回它不会与标题中的 useEffect 混淆
更新 2:我发现这是我在 _app.js 中的保留滚动位置代码,它确实针对该预生成页面以及主页,但实际上不是用户仪表板页面。现在我必须弄清楚如何通过让组件重新渲染来保持滚动位置,因为我已经看到由于同样的问题还有另一段使侧边栏变粘的代码不会启动
这是我的 _app.js 代码:
import React, { useRef, useEffect, memo } from 'react'
import { Provider as NextAuthProvider } from 'next-auth/client'
import { SWRConfig } from 'swr'
import Router, { useRouter } from 'next/router'
import '../public/style.scss'
import { AnimatePresence } from "framer-motion"
export default function MyApp ({ Component, pageProps }) {
const router = useRouter()
const retainedComponents = useRef({})
var isRetainableRoute = false
if (router.pathname == '/' || router.asPath.includes('/author/') || router.asPath.includes('/video/')){
isRetainableRoute = true
}
// Add Component to retainedComponents if we haven't got it already
if (isRetainableRoute && !retainedComponents.current[router.asPath]) {
const MemoComponent = memo(Component)
retainedComponents.current[router.asPath] = {
component: <MemoComponent {...pageProps} />,
scrollPos: 0
}
}
// Save the scroll position of current page before leaving
const handleRouteChangeStart = url => {
if (isRetainableRoute) {
retainedComponents.current[router.asPath].scrollPos = window.scrollY
}
}
// Save scroll position - requires an up-to-date router.asPath
useEffect(() => {
router.events.on('routeChangeStart', handleRouteChangeStart)
return () => {
router.events.off('routeChangeStart', handleRouteChangeStart)
}
}, [router.asPath])
// Scroll to the saved position when we load a retained component
useEffect(() => {
if (isRetainableRoute) {
window.scrollTo(0, retainedComponents.current[router.asPath].scrollPos)
}
}, [Component, pageProps])
return (
<NextAuthProvider
options={{
clientMaxAge: 60,
keepAlive: 61
}}
session={pageProps.session}
>
<SWRConfig
value={{
revalidateOnFocus: false
}}
>
<AnimatePresence exitBeforeEnter>
<div>
<div style={{ display: isRetainableRoute ? 'block' : 'none' }}>
{Object.entries(retainedComponents.current).map(([path, c]) => (
<div
key={path}
style={{ display: router.asPath === path ? 'block' : 'none' }}
>
{c.component}
</div>
))}
</div>
{!isRetainableRoute && <Component {...pageProps} />}
</div>
</AnimatePresence>
</SWRConfig>
</NextAuthProvider>
)
}
【问题讨论】:
标签: javascript node.js reactjs next.js use-effect