React.js页面加载时prompt弹窗重复两次的原因及解决方案
问题原因与解决思路
为什么prompt弹窗会出现两次?
这是**React开发环境下的Strict Mode(严格模式)**导致的。Strict Mode会刻意重复执行组件顶层代码、无依赖的useEffect两次,目的是帮你检测代码中潜在的副作用问题(比如未清理的定时器、非纯函数等)。生产环境下Strict Mode会自动关闭,不会出现这个重复弹窗的情况。
你的几种写法都会触发重复执行:
- 直接在组件顶层写
var tag = prompt(...):组件每次渲染(包括Strict Mode的重复渲染)都会执行这段代码,所以弹窗两次。 - 不带依赖数组的
useEffect:这种useEffect会在组件每次渲染时执行,加上Strict Mode的重复渲染,自然会触发两次prompt。
如何实现只弹一次prompt,且正确保存输入值?
方案1:用useEffect+空依赖数组+useRef(避免警告,保存可变值)
如果只是需要存储输入的标签值,不需要触发组件重新渲染,用useRef来存值是最合适的,配合空依赖数组的useEffect确保只执行一次,再加个标记避免Strict Mode的重复执行:
import { useEffect, useRef } from 'react'; function YourComponent() { // 标记是否已经弹出过prompt const hasPrompted = useRef(false); // 存储输入的标签值 const tagP = useRef("Example"); useEffect(() => { if (!hasPrompted.current) { const inputTag = window.prompt('Enter tag'); // 处理用户点击取消的情况(此时prompt返回null) if (inputTag !== null) { tagP.current = inputTag; console.log(tagP.current); } hasPrompted.current = true; } }, []); // 空依赖数组:仅在组件首次挂载时执行 return <div>当前标签: {tagP.current}</div>; }
方案2:如果需要输入值触发组件渲染(显示到页面)
用useState替代useRef,修改值时会自动触发组件重新渲染:
import { useEffect, useState } from 'react'; function YourComponent() { const hasPrompted = useRef(false); const [tag, setTag] = useState("Example"); useEffect(() => { if (!hasPrompted.current) { const inputTag = window.prompt('Enter tag'); if (inputTag !== null) { setTag(inputTag); } hasPrompted.current = true; } }, []); return <div>当前标签: {tag}</div>; }
能不能不用useEffect或循环?
不行。在React组件中,顶层代码会在每次组件渲染时执行,如果你直接写prompt(...)在顶层,只要组件渲染(包括Strict Mode的重复渲染)就会弹窗。只有通过useEffect(加空依赖数组)才能控制这段代码仅在组件挂载时执行一次,再配合useRef的标记处理Strict Mode的重复执行问题。
内容的提问来源于stack exchange,提问作者CreativeDesign
相关产品推荐
相关产品推荐

