Next.js中Wilayas组件添加事件监听器时重复渲染问题求助
问题:Next.js旅游应用Wilayas组件点击事件重复触发导致卡顿
我正在用Next.js开发一款旅游应用,在Wilayas组件中遇到异常:组件内通过fetch加载SVG地图,通过useEffect为地图每个区域添加点击事件监听器,触发的滑动动画可正常运行。但控制台中调试用的console.log("hello")输出次数随点击次数翻倍递增:点击1次输出1次,点击2次输出3次,点击4次输出15次,最终导致页面卡顿。
Destinations页面直接在代码中内嵌SVG地图,通过React的onClick属性添加相同的事件处理函数,运行完全正常。但由于各区域的SVG地图多达11份,无法全部内嵌,因此需要解决该问题。
Wilayas组件代码
const Wilayas = ({ region }: { region: any }) => { const [wilayas, setWilayas] = useState<HTMLElement[]>([]); const [currentIndex, setCurrentIndex] = useState(0); const [left, setLeft] = useState(0); const [back, setBack] = useState(false); const [forward, setForward] = useState(true); const sectionRef = useRef<HTMLUListElement>(null); const goBack = () => { setCurrentIndex(currentIndex - 1); if (sectionRef.current) { sectionRef.current.style.transform = `translate(${left + 27.278566666666666}vw)`; } const updatedWilayas = [...wilayas]; updatedWilayas.forEach((wilaya) => wilaya?.classList.add("lighten")); updatedWilayas[currentIndex]?.classList.remove("darken"); updatedWilayas[currentIndex - 1]?.classList.add("darken"); updatedWilayas[currentIndex - 1]?.classList.remove("lighten"); setWilayas(() => updatedWilayas); setLeft(left + 27.278566666666666); if (currentIndex === 1) { setBack(false); } else { setForward(true); } }; const goForward = () => { setCurrentIndex(currentIndex + 1); if (sectionRef.current) { sectionRef.current.style.transform = `translate(${left - 27.278566666666666}vw)`; } const updatedWilayas = [...wilayas]; updatedWilayas.forEach((wilaya) => wilaya.classList.add("lighten")); updatedWilayas[currentIndex]?.classList.remove("darken"); updatedWilayas[currentIndex + 1]?.classList.add("darken"); updatedWilayas[currentIndex + 1]?.classList.remove("lighten"); setWilayas(() => updatedWilayas); setLeft(left - 27.278566666666666); if (currentIndex === 8) { setForward(false); } else { setBack(true); } }; const goToExactRegion = useCallback( (index: number) => { setCurrentIndex(index); const updatedWilayas = [...wilayas]; console.log("hello"); updatedWilayas.forEach((wilaya) => wilaya.classList.add("lighten")); updatedWilayas[currentIndex]?.classList.remove("darken"); updatedWilayas[index]?.classList.add("darken"); updatedWilayas[index]?.classList.remove("lighten"); if (index < currentIndex) { sectionRef.current!.style.transform = `translate(${left + (currentIndex - index) * 27.278566666666666}vw)`; if (index === 0) { setBack(false); } setForward(true); setLeft(left + (currentIndex - index) * 27.278566666666666); } else if (index > currentIndex) { sectionRef.current!.style.transform = `translate(${left - (index - currentIndex) * 27.278566666666666}vw)`; if (index === 9) { setForward(false); } setBack(true); setLeft(left - (index - currentIndex) * 27.278566666666666); } setWilayas(() => updatedWilayas); }, [wilayas] ); const handleSwitch = (index: number) => () => { goToExactRegion(index); }; useEffect(() => { if (document.getElementById("region") !== null) { const fetching = async () => { const response = await fetch(`https://ik.imagekit.io/vaqzdpz5y/assets/images/${region.id}/3.svg`); const svgContent = await response.text(); console.log("hello"); document.getElementById("region")!.innerHTML = svgContent; document.getElementById("svg2")!.style.width = "100%"; const wilayat = []; for (let i = 1; i < 11; i++) { const wilaya = document.getElementById(`${i}`); if (wilaya) wilayat.push(wilaya); } setWilayas(wilayat); }; fetching(); } }, []); useEffect(() => { const wilayat: HTMLElement[] = []; for (let i = 1; i < 11; i++) { const wilaya = document.getElementById(`${i}`); if (wilaya) { wilaya.addEventListener("click", handleSwitch(i - 1)); wilayat.push(wilaya); } } return () => { wilayat.forEach((wilaya, i) => { wilaya.removeEventListener("click", handleSwitch(i - 1)); }); }; }, [wilayas, handleSwitch]); return ( <div> ... <div id="region" className="w-[51.5625vw]"></div> </div> )
注:最后一个div用于加载SVG地图。
SVG代码说明
仅需关注每个path元素的ID,示例代码如下:
<svg version="1.1" id="svg2" x="0px" y="0px" viewBox="0 0 207.52948 125.99589" enable-background="new 0 0 982.451 955.452" <defs id="defs63" /> <path id="1" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> <path id="9" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> <path id="8" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> <path id="5" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> <path id="4" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> <path id="6" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> ... <path id="3" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> <path id="10" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> <path id="2" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> <path id="7" fill="#03c988" stroke="#ffffff" stroke-width="0.75" stroke-linecap="round" d="m ..." /> ... </svg>
内容的提问来源于stack exchange,提问作者ashendhiaa
相关产品推荐
相关产品推荐

