Axios请求后弹窗提示与按钮交互异常排查
书籍租赁校验代码异常问题
问题描述
我编写了一段用于校验书籍是否已租赁的代码,Axios请求功能正常,但存在以下问题:
- 当书籍已租赁并完成支付后,点击「Show Book Rented」按钮时,会先弹出提示弹窗,再进入书籍页面;
- 需要双击按钮才能进入书籍,似乎Axios请求后的
setBookIsRent状态更新存在延迟,再次点击才会正常进入并显示正确的弹窗。
相关代码
校验函数代码
function rentChecker(){ try{ //Checking if the book is Rented axios.post('http://***********/getBooksRent', { userID : global.id, bookID : bookShow.id }).then((response) => { const data = response.data; console.log(data[0]) setBookIsRent(data); }) var today = new Date().getTime()/1000; console.log(today); var bookRentTimeStamp = new Date(bookIsRent[0].TimeEnd).getTime()/1000; console.log(bookRentTimeStamp); var checker = (today > bookRentTimeStamp) console.log("Real time is greater than rent time ? Answer--> " + checker) if(bookIsRent[0].bookRented == 1 && (today < bookRentTimeStamp)){ navigation.navigate('WebViewPdf',{paramKey:bookShow}) } else if(checker){ Alert.alert("Forbitten,book not Rented!") } }catch(error){ Alert.alert("Forbitten,book not Rented!") } }
按钮组件代码
<Pressable style = {styles.pressableInsideModal} onPress = {() => { rentChecker() }}> <Text style = {styles.textInsideModal}>Show Book Rented</Text> </Pressable>
问题排查与修复方案
核心问题分析
问题出在异步请求的执行顺序上:Axios发送POST请求是异步操作,你在发送请求后立刻就执行了时间校验、状态判断逻辑,这时候setBookIsRent还没完成状态更新,代码用的还是之前的旧状态值。所以第一次点击时,判断逻辑基于旧数据触发错误提示;第二次点击时,状态已经更新,才能得到正确的判断结果。
另外,React的状态更新本身也是异步的,即使调用了setBookIsRent,也无法在回调外立刻拿到新的状态值,这进一步加剧了问题。
修复代码
把所有依赖请求返回数据的逻辑,全部移到Axios的.then()回调内部,并且直接使用请求返回的data进行判断(不用依赖状态更新),修改后的代码如下:
function rentChecker(){ axios.post('http://***********/getBooksRent', { userID : global.id, bookID : bookShow.id }).then((response) => { const data = response.data; console.log(data[0]) setBookIsRent(data); // 所有判断逻辑移到回调内,确保使用最新的请求数据 const today = new Date().getTime()/1000; console.log(today); const bookRentTimeStamp = new Date(data[0].TimeEnd).getTime()/1000; console.log(bookRentTimeStamp); const checker = today > bookRentTimeStamp; console.log("Real time is greater than rent time ? Answer--> " + checker) if(data[0].bookRented === 1 && !checker){ navigation.navigate('WebViewPdf',{paramKey:bookShow}) } else if(checker){ Alert.alert("Forbitten,book not Rented!") } }).catch(error => { // 捕获请求失败的情况 Alert.alert("Forbitten,book not Rented!") }) }
额外优化点
- 用
const替代var,避免变量提升带来的潜在问题; - 将Axios请求的错误捕获移到
.catch()中,更精准地处理请求失败场景; - 把
today < bookRentTimeStamp改成!checker,逻辑更简洁一致。
内容的提问来源于stack exchange,提问作者Thanos Rom
相关产品推荐
相关产品推荐

