React Native中无法访问State属性的问题排查求助
问题:React State更新后控制台输出为空数组,但UI显示正常?
我在State中定义了两个数组:
const [offers, setOffers] = useState([]); const [redemptions, setRedemptions] = useState([]);
通过以下函数更新这些属性:
useEffect(() => { getData(); }, []); const getData = () => { Promise.all([getVenue(), getUserData(), getOffers(), getRedemptions()]) .then(() => { console.log("OFFERS", offers); // 此处OFFERS为[]?? console.log("REDEMPTIONS", redemptions); // 此处REDEMPTIONS为[]?? }) .catch((error) => { console.log(error); }) .finally(() => { setLoading(false); }); }; const getOffers = async () => { const offers = await fetchOffers(id); setOffers(offers); }; const getRedemptions = async () => { const redemptions = await fetchRedemptions(user.uid, id); setRedemptions(redemptions); };
但在所有函数执行完成后,控制台输出的是空数组,不过UI却能显示正确的值。请问忽略了什么?
解答
核心原因是React的State更新是异步的,且闭包会捕获当前渲染周期的State值:
getOffers和getRedemptions内部调用setOffers/setRedemptions时,只是向React发起了State更新请求,不会立即修改当前闭包中的offers和redemptions变量。Promise.all的then回调执行时,组件还没完成重新渲染,此时回调里访问的offers和redemptions依然是初始渲染时捕获的空数组值。- 当React完成State更新并触发组件重新渲染后,新的State值会被UI读取,所以页面能正常显示数据。
针对不同需求,有两种解决方式:
方式一:监听State变化执行逻辑
如果需要在State更新完成后做后续处理,直接通过useEffect监听offers和redemptions:
useEffect(() => { // 确保数据已加载完成 if (offers.length && redemptions.length) { console.log("最新OFFERS", offers); console.log("最新REDEMPTIONS", redemptions); // 执行其他依赖最新数据的逻辑 } }, [offers, redemptions]);
方式二:在Promise回调中直接接收返回值
如果必须在Promise.all的回调里拿到最新数据,可以让异步函数直接返回请求结果,不在内部调用setState,而是统一在then中更新State并使用数据:
const getData = () => { Promise.all([getVenue(), getUserData(), getOffers(), getRedemptions()]) .then(([_, __, offersData, redemptionsData]) => { // 直接拿到请求返回的最新数据 console.log("OFFERS", offersData); console.log("REDEMPTIONS", redemptionsData); // 统一更新State setOffers(offersData); setRedemptions(redemptionsData); }) .catch((error) => { console.log(error); }) .finally(() => { setLoading(false); }); }; const getOffers = async () => { // 返回请求结果 return await fetchOffers(id); }; const getRedemptions = async () => { // 返回请求结果 return await fetchRedemptions(user.uid, id); };
内容的提问来源于stack exchange,提问作者David Henry
相关产品推荐
相关产品推荐

