React Native中带指定依赖时如何让useEffect内异步函数仅执行一次?
解决方法
你的代码存在两个核心问题:
- React开发环境的Strict Mode会自动执行两次useEffect用于检测副作用,加上你依赖了
url和renderbool,首次渲染后setUrl会触发useEffect再次执行; - 在异步函数里调用
setUrl后立即判断url,此时url还是旧值(因为setUrl是异步更新状态),导致后续隐藏启动页和更新renderbool的逻辑不会触发,反而让renderbool一直为false,使得每次useEffect执行都会进入API调用的判断。
修正后的代码
import { useState, useEffect, useRef } from 'react'; const [url, setUrl] = useState(''); const [renderbool, setRenderbool] = useState(false); const hasFetched = useRef(false); // 标记是否已经获取过数据 // 专门用于获取数据的useEffect,确保只执行一次 useEffect(() => { const fetchData = async () => { // 用ref判断是否已经执行过,避免Strict Mode的重复调用和后续触发 if (!hasFetched.current && !renderbool) { hasFetched.current = true; try { const urlsdata = await storage().ref('/main.jpg').getDownloadURL(); setUrl(urlsdata); } catch (err) { // 可在此添加错误处理 console.error('获取图片链接失败:', err); } } }; fetchData(); }, [renderbool]); // 保留renderbool作为依赖,确保只有未渲染时才可能触发 // 监听url的变化,处理启动页隐藏和renderbool更新 useEffect(() => { if (url) { SplashScreen.hide(); setRenderbool(true); } }, [url]); // 依赖url,当url有值时执行
关键调整点
- 使用
useRef的hasFetched标记,确保API请求只执行一次,不受Strict Mode或状态更新触发的useEffect影响; - 将数据获取和状态更新后的逻辑拆分到两个useEffect中,避免异步状态更新的时机问题;
- 移除
url作为数据获取useEffect的依赖,避免setUrl后再次触发该useEffect; - 在监听
url的useEffect中处理启动页隐藏和renderbool的更新,此时url已经是最新值,逻辑能正确触发。
内容的提问来源于stack exchange,提问作者user19476497
相关产品推荐
相关产品推荐

