当我想检查窗口对象的属性是不是在这里时,useEffect 中的无限循环
Posted
技术标签:
【中文标题】当我想检查窗口对象的属性是不是在这里时,useEffect 中的无限循环【英文标题】:Infinite for loop in useEffect when i want to check if a property of window object is here当我想检查窗口对象的属性是否在这里时,useEffect 中的无限循环 【发布时间】:2022-01-24 02:50:29 【问题描述】:我想在加载时检查对象窗口是否具有属性 VL.refCode。 我为我的网站使用病毒循环,并在用户注册时将病毒循环放入 window.VL 对象的属性 refCode。
我在useEffect中放了一个for循环来检查这个属性是否存在,不幸的是它变成了一个无限循环。
useEffect(() =>
if(window.VL)
if(window.VL.refCode)
setCryptoButtonMessage(t('common:cryptoButton_already_register'))
console.log('useEffect :user already register')
else
console.log('useEffect : window.vl.refcode not exist')
else
setCryptoButtonMessage(t('common:cryptoButton_title_waitlist'))
// t is for translation with i18n
,[t]);
此解决方案不起作用,因为病毒循环在第一次渲染后创建 window.VL 对象 1 到 2 秒最大。 如果我设置了 setTimeout,对于使用移动设备/慢 3g/没有光纤的用户来说,这不是一个有效的解决方案
所以我使用这个解决方案
useEffect(() =>
let animation;
const check = () =>
console.log('je suis dans check');
console.log('je suis dans for');
if ((Object.prototype.hasOwnProperty.call(window.VL, 'refCode')))
console.log('je trouve refCode ');
setCryptoButtonMessage(t('common:cryptoButton_already_register'))
cancelAnimationFrame(animation);
return;
animation = requestAnimationFrame(check);
;
animation = requestAnimationFrame(check);
,[t]);
但是这个解决方案在 window.VL.refCode 存在之前永远不会停止......并不是网站性能的最佳解决方案......
我尝试放置一个“模拟计时器”,但它变成了一个无限循环......
useEffect(() =>
for (let i = 1; i < 10000; i += 1)
let animation;
const check = () =>
if ((Object.prototype.hasOwnProperty.call(window.VL, 'refCode')))
setCryptoButtonMessage(t('common:cryptoButton_already_register'))
cancelAnimationFrame(animation);
return;
animation = requestAnimationFrame(check);
;
animation = requestAnimationFrame(check);
,[t]);
【问题讨论】:
【参考方案1】:我不知道在窗口上创建对象时自动告知的任何方式 - 据我所知,唯一的方法是使用投票。如果是我,我会将轮询 ref 代码的逻辑抽象到一个新的钩子中:
import useEffect, useRef, useState from 'react';
const useRefCode = (pollTimeMillis = 1000) =>
const timeoutRef = useRef(undefined);
const [refCode, setRefCode] = useState(window.VL?.refCode);
const cancelTimeout = () =>
if (!timeoutRef.current) return;
clearTimeout(timeoutRef.current);
timeoutRef.current = undefined;
;
useEffect(() =>
if (refCode) return;
setTimeout(() =>
setRefCode(window.VL?.refCode || undefined),
pollTimeMillis
);
return cancelTimeout;
, [refCode]);
return refCode;
那么你的其他组件想要根据 ref 代码改变消息就变得很简单了:
const OtherComponent = () =>
const refCode = useRefCode();
const translationKey = refCode
? 'common:cryptoButton_already_register'
: 'common:cryptoButton_title_waitlist';
return (
<div>t(translationKey)</div>
);
【讨论】:
以上是关于当我想检查窗口对象的属性是不是在这里时,useEffect 中的无限循环的主要内容,如果未能解决你的问题,请参考以下文章