React Native中Firebase数据未获取完成就执行计算函数问题求助
问题原因
核心bug和Firebase请求时序无关,出在React状态更新的异步特性上:你调用setNewProduct(myProduct)后立刻执行myData(),此时newProduct这个state还没完成更新,myData里读取到的newProduct是更新前的旧值(大概率是空数组),自然没法基于刚拉取的经纬度做距离计算。
另外原代码还有两个隐藏问题:
- 直接修改state数组里的元素,属于状态直接篡改,容易触发页面不刷新、状态错乱
- 未声明就直接给
myNewProduct、mydistance赋值,会污染全局作用域引发未知bug
修复代码
直接把从Firestore拉取到的最新商品数组作为参数传入计算函数,完全跳过等待state更新的环节,从根源避免时序问题:
function fetchProducts() { const myProduct = []; db.collection("item") .orderBy("createdAt", "desc") .get() .then((snapshot) => { snapshot.docs.forEach((doc) => { const { createdAt, category, image, values, latitude, longitude } = doc.data(); myProduct.push({ createdAt, id: doc.id, latitude, longitude, category, image, values, }); }); setNewProduct(myProduct); // 直接传入最新的商品数组,不依赖state更新后的值 myData(myProduct); }); } const myData = (productList) => { GetCurrentLocation().then(() => { // 遍历生成带距离的新数组,不直接修改原对象 const productWithDistance = productList.map((element) => { const distance = calcDistance( element.latitude, element.longitude, newLatitude, newLongitude ); return { ...element, distance }; }); // 按距离排序后更新展示用的商品列表 productWithDistance.sort((a, b) => a.distance - b.distance); setProduct(productWithDistance); }); };
补充说明
- React的state更新是批量异步执行的,只要执行
setXxx后下一行代码立刻读取xxx,拿到的一定是更新前的旧值。如果后续逻辑必须依赖更新后的state,除了上面直接传参的方案,也可以用useEffect监听对应state变化,在state更新完成后再触发后续逻辑。 - 所有涉及state的修改都要遵循不可变原则,不要直接给state里的对象、数组属性赋值,优先用展开运算符、map/filter等返回新值的方法生成新的状态对象,避免隐性bug。
内容的提问来源于stack exchange,提问作者eugene
相关产品推荐
相关产品推荐

