Next.js中useEffect触发两次GET请求,原因是什么?
解决React组件中API GET请求重复触发的问题
重复请求的核心原因
最常见的触发原因是React开发环境的严格模式(Strict Mode),它会刻意重复执行useEffect、组件初始化等逻辑,用来检测潜在的副作用问题。这种重复仅在开发环境存在,生产环境不会出现,但考虑到你的API会触发Active Directory操作,必须确保副作用逻辑是幂等的,或者添加防护机制避免重复执行。
具体修复步骤
1. 添加请求防护标志
在useEffect中加入挂载状态标志,防止重复执行请求逻辑,同时避免组件卸载后更新状态:
function Ad() { const [data, setData] = useState(null) const [isLoading, setLoading] = useState(false) const [isRemoved, setIsRemoved] = useState(null) // 用状态管理移除状态,替代直接DOM操作 useEffect(() => { let isMounted = true // 仅在未获取数据时发起请求 if (isMounted && !data) { setLoading(true) fetch('../api/decom/ad') .then(response => response.json()) .then(fetchedData => { if (isMounted) { setData(fetchedData) setLoading(false) if (fetchedData.exists) { handleRemove() } } }) .catch(error => { if (isMounted) setLoading(false) }) } // 组件卸载时重置标志 return () => { isMounted = false } }, [data]) const handleRemove = () => { fetch("../api/decom/ad", { method: "DELETE" }) .then(response => response.json()) .then(removeData => setIsRemoved(removeData.removed)) .catch(error => { /* 处理删除请求错误 */ }) } // 用状态控制渲染,替代DOM操作 if (data?.exists) { return ( <a className={styles.card}> <h2>AD</h2> <p>Exists: { greenCircle } </p> <div className={styles.parent}> <p className={styles.child}>Removed:</p> {isRemoved === null ? ( <div><div className={styles.loader}><div></div><div></div><div></div></div></div> ) : ( <p>Removed: {isRemoved ? greenCircle : redCircle}</p> )} </div> </a> ) } if (data?.exists === false) { return ( <a className={styles.card}> <h2>AD</h2> <p>Exists: {redCircle} </p> <p>Removed:{redCircle}</p> </a> ) } if (isLoading) { return ( <a className={styles.card}> <h2>AD</h2> <div className={styles.parent}> <p className={styles.child}>Exists:</p> <div><div className={styles.loader}><div></div><div></div><div></div></div></div> </div> <p>Removed:{redCircle}</p> </a> ) } return null }
2. 替换DOM操作为React状态管理
原代码中直接操作DOM的方式不符合React的状态管理逻辑,改用isRemoved状态控制移除状态的渲染,避免DOM操作引发的冲突。
3. 后端幂等性保障
如果你的API不是幂等的(比如重复执行DELETE会多次删除AD对象),必须在后端添加校验逻辑,比如通过资源状态或请求ID判断,避免重复操作带来的风险。
内容的提问来源于stack exchange,提问作者N4NO
相关产品推荐
相关产品推荐

