英文:
React component keeps re-rendering whenever screen is minimized or another tab is opened
问题
以下是您要翻译的内容:
我在我的投资组合网站中有一个组件,它会每隔几秒钟创建一个对角线移动的圆圈。问题是,当我最小化屏幕或切换选项卡并在一分钟后回来时,会同时创建许多圆圈,并填满屏幕。我不确定为什么会发生这种情况。
您可以在我的网站上实时查看效果:https://khaledalhariri.com
目前我设置最多在屏幕上显示6个圆圈。所以当我最小化窗口并在一分钟后打开它时,会同时创建6个圆圈,这是个问题...如果我没有设置这个6个圆圈的限制,那么将会同时创建无数个圆圈。
代码部分不需要翻译。
英文:
I have a component in my portfolio website that creates a diagonally moving circle every couple of seconds. The problem is that when I minimize the screen or change the tab and come back after a minute, many circles will be created at the same time and the screen gets filled with them. I am not sure why this happens.
You can see the effect live in my website: https://khaledalhariri.com
Currently I have it set to have 6 circles at most in the screen. So when I minimize the window and open it after a minute, 6 circles are created at the same time which is an issue.. if I didnt set that limit of 6 circles then countless circles would have been created at the same time.
Code:
import { useEffect, useRef } from 'react';
import './banner-skills.component.css';
import SKILLS_DATA, { Skill } from '../../data/skills';
const BannerSkills = () => {
const CREATE_CIRCLE_MS = 4500;
const CREATE_CIRCLE_MS_MOBILE = 7000;
const ARRAY_OF_SKILLS: Skill[] = [];
const isFirstRender = useRef(true);
useEffect(() => {
const skillsContainer = document.getElementsByClassName('banner-skills-container')[0];
let minScreenSize = window.screen.width * 0.08;
let maxScreenSize = window.screen.width * 0.85;
let maxCircles = 6;
let prevInitPos = Math.floor(Math.random() * maxScreenSize) - minScreenSize;
const createDiagonalCircle = () => {
if(window.screen.width <= 500) {
minScreenSize = window.screen.width * 0.8;
maxCircles = 4;
}
else {
minScreenSize = window.screen.width * 0.08;
maxCircles = 6;
}
if(ARRAY_OF_SKILLS.length >= maxCircles) {
return;
}
const circle = document.createElement('div');
circle.classList.add('skill-circle');
skillsContainer.appendChild(circle);
const logo = document.createElement('img');
let randomSkill = SKILLS_DATA[Math.floor(Math.random() * SKILLS_DATA.length)];
while(ARRAY_OF_SKILLS.indexOf(randomSkill) >= 0) {
randomSkill = SKILLS_DATA[Math.floor(Math.random() * SKILLS_DATA.length)];
}
logo.src = randomSkill.img;
ARRAY_OF_SKILLS.push(randomSkill);
circle.appendChild(logo);
let size = Math.floor(Math.random() * 70) + 70;
circle.style.width = size + 'px';
circle.style.height = size + 'px';
let posTop = -150;
let posLeft = Math.floor(Math.random() * maxScreenSize) - minScreenSize;
while(Math.abs(posLeft - prevInitPos) < (window.screen.width * 0.13)) {
posLeft = Math.floor(Math.random() * maxScreenSize) - minScreenSize;
}
prevInitPos = posLeft;
let moveCirclesInterval = setInterval(frame, size - (size * 0.65));
function frame() {
if (posTop === 500) {
skillsContainer.removeChild(circle);
ARRAY_OF_SKILLS.splice(ARRAY_OF_SKILLS.indexOf(randomSkill), 1);
clearInterval(moveCirclesInterval);
} else {
posTop++;
posLeft++;
circle.style.top = posTop + 'px';
circle.style.left = posLeft + 'px';
circle.style.visibility = 'visible';
}
}
isFirstRender.current = false;
}
if(isFirstRender.current === true) {
createDiagonalCircle();
if(window.screen.width <= 500) {
let spawnCirclesInterval = setInterval(createDiagonalCircle, CREATE_CIRCLE_MS_MOBILE);
return () => clearInterval(spawnCirclesInterval);
}
else {
let spawnCirclesInterval = setInterval(createDiagonalCircle, CREATE_CIRCLE_MS);
return () => clearInterval(spawnCirclesInterval);
}
}
}, [])
return (
<div className="banner-skills-container"></div>
)
}
export default BannerSkills
The circles are created in the useEffect and I have tried to find out if the page is being re-redenderd or not to stop it but I didn't find anything to work.
答案1
得分: 1
你没有在用户切换标签页或最小化屏幕时清除setInterval函数的时间间隔。createDiagonalCircle 在后台继续运行,即使用户没有主动查看页面,也会创建圆圈。
要解决这个问题,你可以使用window.blur和window.focus事件来分别停止和重新启动时间间隔。以下是一个示例实现:
useEffect(() => {
const skillsContainer = document.getElementsByClassName('banner-skills-container')[0];
let minScreenSize = window.screen.width * 0.08;
let maxScreenSize = window.screen.width * 0.85;
let maxCircles = 6;
let prevInitPos = Math.floor(Math.random() * maxScreenSize) - minScreenSize;
let intervalId: any;
const createDiagonalCircle = () => {
// ... 其余的代码
};
const handleVisibilityChange = () => {
if (document.hidden) {
clearInterval(intervalId);
} else {
intervalId = setInterval(createDiagonalCircle, window.screen.width <= 500 ? CREATE_CIRCLE_MS_MOBILE : CREATE_CIRCLE_MS);
}
};
if (window.screen.width <= 500) {
minScreenSize = window.screen.width * 0.8;
maxCircles = 4;
} else {
minScreenSize = window.screen.width * 0.08;
maxCircles = 6;
}
window.addEventListener('blur', () => clearInterval(intervalId));
window.addEventListener('focus', () => intervalId = setInterval(createDiagonalCircle, window.screen.width <= 500 ? CREATE_CIRCLE_MS_MOBILE : CREATE_CIRCLE_MS));
document.addEventListener('visibilitychange', handleVisibilityChange);
intervalId = setInterval(createDiagonalCircle, window.screen.width <= 500 ? CREATE_CIRCLE_MS_MOBILE : CREATE_CIRCLE_MS);
return () => {
clearInterval(intervalId);
window.removeEventListener('blur', () => clearInterval(intervalId));
window.removeEventListener('focus', () => intervalId = setInterval(createDiagonalCircle, window.screen.width <= 500 ? CREATE_CIRCLE_MS_MOBILE : CREATE_CIRCLE_MS));
document.removeEventListener('visibilitychange', handleVisibilityChange);
}
}, [])
英文:
You don't cleare the interval of the setInterval function when the user navigates away from the tab or minimizes the screen. createDiagonalCircle continues to run in the background and creates circles even when the user is not actively viewing the page.
To fix this issue, you can use the window.blur and window.focus events to stop and restart the interval respectively. Here's an example implementation:
useEffect(() => {
const skillsContainer = document.getElementsByClassName('banner-skills-container')[0];
let minScreenSize = window.screen.width * 0.08;
let maxScreenSize = window.screen.width * 0.85;
let maxCircles = 6;
let prevInitPos = Math.floor(Math.random() * maxScreenSize) - minScreenSize;
let intervalId: any;
const createDiagonalCircle = () => {
// ... rest of the code
};
const handleVisibilityChange = () => {
if (document.hidden) {
clearInterval(intervalId);
} else {
intervalId = setInterval(createDiagonalCircle, window.screen.width <= 500 ? CREATE_CIRCLE_MS_MOBILE : CREATE_CIRCLE_MS);
}
};
if (window.screen.width <= 500) {
minScreenSize = window.screen.width * 0.8;
maxCircles = 4;
} else {
minScreenSize = window.screen.width * 0.08;
maxCircles = 6;
}
window.addEventListener('blur', () => clearInterval(intervalId));
window.addEventListener('focus', () => intervalId = setInterval(createDiagonalCircle, window.screen.width <= 500 ? CREATE_CIRCLE_MS_MOBILE : CREATE_CIRCLE_MS));
document.addEventListener('visibilitychange', handleVisibilityChange);
intervalId = setInterval(createDiagonalCircle, window.screen.width <= 500 ? CREATE_CIRCLE_MS_MOBILE : CREATE_CIRCLE_MS);
return () => {
clearInterval(intervalId);
window.removeEventListener('blur', () => clearInterval(intervalId));
window.removeEventListener('focus', () => intervalId = setInterval(createDiagonalCircle, window.screen.width <= 500 ? CREATE_CIRCLE_MS_MOBILE : CREATE_CIRCLE_MS));
document.removeEventListener('visibilitychange', handleVisibilityChange);
}
}, [])
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论