React中useEffect内修改全局变量不生效问题咨询
问题原因
useEffect回调会在组件首次渲染完成后才执行,且回调内部的数据库查询是异步操作。组件首次渲染时,外部的console.log会先执行,此时异步请求还未返回结果,全局变量还是初始空值。- 普通全局变量的变更不会触发React组件重新渲染,所以哪怕后续异步请求完成修改了全局变量,组件也不会重新执行代码逻辑,外部的打印自然看不到更新后的值。
解决方案
方案1:将变量存在组件state中(推荐,符合React设计规范)
如果这些变量只在当前Statsview组件内使用,直接用useState存储即可,state更新会自动触发组件重渲染:
function Statsview( {backButton} ) { const urlParams = new URLSearchParams(window.location.search); const name = urlParams.get('name'); // 声明对应的状态存储变量 const [O_name, setO_name] = useState(""); const [A_name, setA_name] = useState(""); const [A_platform, setA_platform] = useState(""); const [C_name, setC_name] = useState(""); useEffect(() => { database.collection('USERS').where('name','==',name).get().then(snapshot => { snapshot.forEach(doc => { const data = doc.data() // 更新状态触发重渲染 setO_name(data.overwatch); setA_name(data.apexLegends); setA_platform(data.apexLegendsPlatform); setC_name(data.chess); }) }).catch(error => console.log(error)) },[name]); // 把name加入依赖数组,避免闭包问题 // 状态更新触发重渲染后,这里就能打印到最新值 console.log("oname: ",O_name) console.log("aname: ",A_name) console.log("aplat: ",A_platform) console.log("cname: ",C_name) // ...其余逻辑 }
方案2:必须使用全局变量的场景
如果这些变量需要在多个无关组件之间共享,必须用全局变量的话,修改完全局变量后手动触发当前组件重渲染即可:
var O_name = ""; var A_name = ""; var A_platform = ""; var C_name = ""; function Statsview( {backButton} ) { const urlParams = new URLSearchParams(window.location.search); const name = urlParams.get('name'); // 声明一个无意义状态用来触发重渲染 const [, forceUpdate] = useState(0); useEffect(() => { database.collection('USERS').where('name','==',name).get().then(snapshot => { snapshot.forEach(doc => { var data = doc.data() O_name = data.overwatch; A_name = data.apexLegends; A_platform = data.apexLegendsPlatform; C_name = data.chess; // 更新状态触发组件重渲染 forceUpdate(prev => prev + 1); }) }).catch(error => console.log(error)) },[name]); console.log("oname: ",O_name) console.log("aname: ",A_name) console.log("aplat: ",A_platform) console.log("cname: ",C_name) // ...其余逻辑 }
注意:如果其他组件也需要感知这些全局变量的变更,建议使用Context、Zustand等全局状态管理方案,不要用普通全局变量,避免多组件状态不同步的问题。
内容的提问来源于stack exchange,提问作者Cole
相关产品推荐
相关产品推荐

