Javascript 如何在header组件(ReactJS/Next.js)中使用effect
我有一个header.js组件,它出现在我的next.js/react项目的每个页面上 在里面,我创建了一个带有旋转的打字机效果,所以为了启动它,我在useEffect中添加了如下代码:Javascript 如何在header组件(ReactJS/Next.js)中使用effect,javascript,node.js,reactjs,next.js,use-effect,Javascript,Node.js,Reactjs,Next.js,Use Effect,我有一个header.js组件,它出现在我的next.js/react项目的每个页面上 在里面,我创建了一个带有旋转的打字机效果,所以为了启动它,我在useEffect中添加了如下代码: export default function Header () { useEffect(() => { let delay = 2200; let input = document.getElementsByClassName('myButton')[0], i
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一样重新创建某种类型的文档.ready
,尽管我在使用useffect
时遇到了两个问题,一个是如果我更改页面,标题保持不变,但效果代码看起来是死的(不再显示任何文本),另一个是,如果我回到主页,代码在第一次加载时工作正常,现在它显示了快速成功中的两个旋转实例(好像有两个useEffect同时运行,一个在另一个之上,或者类似的东西)
我越来越了解useEffect是如何工作的,我知道[]使它在页面加载时运行一次,但我认为这就是我的案例所需要的,看起来我错了。我是否应该在[]中传递可以解决上述两个问题的内容?我尝试使用next.js router,传递router.pathname,让它在每次页面更改时再次运行,但不起作用
更新:我注意到上述两种奇怪的行为只有在从主页转到预先生成的页面(通过staticpath和staticProps)并返回时才会发生。
如果我从主页转到用户仪表板(服务器端渲染)并返回,它不会与标题中的useEffect混淆
更新2:我发现是我在\u app.js中的retain scroll position代码确实针对预生成的页面以及主页,但实际上不是用户仪表板页面。现在,我必须弄清楚如何通过让组件重新渲染来保持滚动位置,因为我已经看到,由于同样的问题,另一段代码使边栏粘滞,但没有启动
这是我的\u 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>
)
}
import React,{useRef,useffect,memo}来自“React”
从“下一个身份验证/客户端”导入{Provider as nextuthprovider}
从“swr”导入{SWRConfig}
从“下一个/路由器”导入路由器{useRouter}
导入“../public/style.scss”
从“帧运动”导入{AnimatePresence}
导出默认函数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
}
//如果我们还没有将组件添加到retainedComponents中
if(isRetainableRoute&!retainedComponents.current[router.asPath]){
常量备忘录组件=备忘录(组件)
retainedComponents.current[路由器.asPath]={
组成部分:,
位置:0
}
}
//离开前保存当前页面的滚动位置
常量handleRouteChangeStart=url=>{
如果(isRetainableRoute){
retainedComponents.current[router.asPath].scrollPos=window.scrollY
}
}
//保存滚动位置-需要最新的router.asPath
useffect(()=>{
路由器.events.on('routeChangeStart',HandlerRouteChangeStart)
return()=>{
router.events.off('routeChangeStart',HandlerRouteChangeStart)
}
},[router.asPath])
//加载保留组件时,滚动至保存位置
useffect(()=>{
如果(isRetainableRoute){
scrollTo(0,retainedComponents.current[router.asPath].scrollPos)
}
},[Component,pageProps])
返回(
{Object.entries(retainedComponents.current).map([path,c])=>(
{c.component}
))}
{!isRetainableRoute&&}
)
}
通过在setTimeout
中递归调用cycleText
,您创建了一个永不结束的函数,即使在头组件卸载时(在更改页面时发生)。当移动到再次包含页眉组件的页面时,将创建该页眉组件,并在装入时再次执行useffect
,从而启动另一个无休止的cycleText
函数,以此类推
您可以在cycleText
函数中放置console.log
,以查看当您移动到另一个页面并返回到具有页眉的页面时,它会越来越快地进行日志记录
我认为最好避免使用递归无止境函数来避免使用堆栈内存,而使用setInterval
。更重要的是:不要忘记在卸载组件时停止您的功能。对于useffect
它在返回时完成,您可以在那里调用clearInterval
您可以这样做:
useffect(()=>{
设延时=2200;
让输入=document.getElementsByCassName('myButton')[0],
指数=0;
常量间隔=设置间隔(()=>{
让randomItem=items[Math.floor(Math.random()*items.length)];
按钮.setAttribute('值',“单击”+随机项);
索引++;
如果(索引>=items.length){
索引=0
}
},延误);
return()=>{
间隔时间;
};
}, []);
您可以在一个组件中声明多个useffect()
。我想这对你有帮助
在标题组件中,保持第一个useffect()
不变。添加第二个,如下所示:
useEffect(() => {
... code to update state
}, [updatedProp]);
这里的关键是数组中的
updatedProp
项。这告诉useEffect在特定属性或变量更改时触发。将updatedProp
替换为您希望此useEffect触发的变量/道具。遗憾的是,它不起作用,无论如何,感谢我使用它,因为它肯定比超时更有意义。阿尔托一世