React中弹窗重复弹出问题求助:移除StrictMode后遇ResizeObserver警告
拼图游戏弹窗重复触发与StrictMode移除后的警告问题
我开发了一款拼图游戏,完成拼图后会弹出提示alert,接着弹出确认窗口询问是否继续游玩,但目前这些弹窗会重复出现两次。我尝试移除index.js中的React.StrictMode,却出现了"ResizeObserver loop completed with undelivered notifications."警告,且应用无法维持原有正常运行状态。
App.js 代码
import React, { useState } from "react"; import "./App.css"; import "./puzzle.css"; import { JigsawPuzzle } from "react-jigsaw-puzzle/lib"; import "react-jigsaw-puzzle/lib/jigsaw-puzzle.css"; import catImg from "./cat.jpeg"; import elephantImg from "./elephant.jpg"; import carImg from "./car.jpg"; import kidsImg from "./kids.jpg"; import sheepImg from "./sheep.png"; const puzzleImages = [catImg, elephantImg, carImg, kidsImg, sheepImg]; function App() { const [imageIndex, setImageIndex] = useState(getRandomIndex()); function getRandomIndex() { return Math.floor(Math.random() * puzzleImages.length); } const handlePlayAgain = () => { const confirmPlayAgain = window.confirm("Do you want to play another puzzle?"); if (confirmPlayAgain){ const newIndex = getRandomIndex(); setImageIndex(newIndex); } else { alert("Thank you for playing") } }; const handleSolved = () => { alert("Good job!"); handlePlayAgain(); }; return ( <> <h2 className="tag">Un-puzzle the pieces</h2> <JigsawPuzzle imageSrc={puzzleImages[imageIndex]} rows={2} columns={2} onSolved={handleSolved} className="jigsaw-puzzle" /> </> ); } export default App;
Index.js 代码
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> ); reportWebVitals();
问题解决办法
弹窗重复触发的原因
React StrictMode在开发环境下会双重调用组件内的事件回调、状态更新逻辑,目的是检测潜在副作用。handleSolved被调用两次,导致弹窗重复弹出。
解决弹窗重复的方法
不用移除StrictMode,用以下两种方式处理:
方式1:状态标记控制触发次数
给App组件加一个状态,标记是否已经触发过完成逻辑,避免重复执行:
function App() { const [imageIndex, setImageIndex] = useState(getRandomIndex()); const [hasSolved, setHasSolved] = useState(false); // 新增状态 function getRandomIndex() { return Math.floor(Math.random() * puzzleImages.length); } const handlePlayAgain = () => { const confirmPlayAgain = window.confirm("要再来一局吗?"); if (confirmPlayAgain){ const newIndex = getRandomIndex(); setImageIndex(newIndex); setHasSolved(false); // 重置标记,允许下一次触发 } else { alert("感谢游玩!") } }; const handleSolved = () => { if (!hasSolved) { setHasSolved(true); alert("太棒了!"); handlePlayAgain(); } }; // 其余代码不变 }
方式2:防抖函数限制执行频率
用防抖函数让handleSolved在短时间内只执行一次:
// 先实现一个简单的防抖函数 const debounce = (func, delay) => { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => func(...args), delay); }; }; function App() { // 其余状态不变 // 给handleSolved加防抖 const handleSolved = debounce(() => { alert("太棒了!"); handlePlayAgain(); }, 100); // 其余代码不变 }
移除StrictMode后的ResizeObserver警告处理
这个警告来自react-jigsaw-puzzle库的内部实现,不影响功能,可通过以下方式消除:
在index.js最顶部添加代码,过滤掉无效的ResizeObserver通知:
const originalRO = window.ResizeObserver; window.ResizeObserver = class extends originalRO { constructor(callback) { super((entries, observer) => { entries = entries.filter(entry => entry.target.isConnected); callback(entries, observer); }); } }; // 原index.js代码...
内容的提问来源于stack exchange,提问作者Manal Ateeq
相关产品推荐
相关产品推荐

