我有一个名为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>
)
}