Expo React Native特定iOS设备TouchableOpacity无响应问题排查
基于Expo React Native开发的订单处理应用出现异常:用户点击购买流程末尾的「ORDER NOW」按钮时,按钮正常高亮但无后续反馈,服务器无请求日志,仅按钮出现闪烁效果。
但当信息缺失(如未填地址、未选日期)时,能正常弹出提示框,说明onPress事件正常触发。
已尝试更新应用、重启设备、重装应用、登出登录、更换账号等操作,问题依旧。两台登录同一iCloud账号的iPhone(13和11)均出现该问题,怀疑是否与iCloud设置限制有关。
相关代码
「ORDER NOW」按钮代码
<TouchableOpacity onPress={formikprops.handleSubmit} style={[{ marginTop: 45 }, shadow.standard]}> <View style={{ backgroundColor: foodhiRed, justifyContent: "center", height: 50, alignSelf: "center", alignItems: "center", width: Dimensions.get('window').width * 0.8, borderRadius: 6, }}> <Text style={[cartStyle.cartFloatingBarText, { fontSize: 16 }]}> {loading ? <Loading /> : "Jetzt bestellen"} </Text> </View> </TouchableOpacity>
Formik的handleSubmit代码
<Formik initialValues={{ address: shipping_address && `${shipping_address.street_1}, ${shipping_address.city}, ${shipping_address.postcode}`, deliveryDate: selectedDate, deliveryTime: selectedTime, immediateDelivery, moreDetails: deliveryMessage }} onSubmit={(values) => { if (selectedDate) { if (shipping_address) { handleCallback(values) } else Alert.alert("Alert", "Please provide an address") } else Alert.alert("Alert", "Please specify a date") }}
handleCallback及后续提交逻辑代码
const confirmSubmit = (values) => { // IF CONDITION IS MET, AND ORDER IS WITHIN TIME CUTOFF dispatch(loadingStart()); // CHECK IF THERE'S AN ADDRESS REGISTERED if (!userProfile.fk_shipping_address) { Alert.alert("Addresse", "You must specify an address"); dispatch(loadingStop()); } else { const orderData = { delivery_date: values.deliveryDate, total: (values.immediateDelivery ? subTotal : subTotal + farmer.delivery_fee).toFixed(3), delivery_fee: values.immediateDelivery ? 0 : farmer.delivery_fee, delivery_note: values.moreDetails, immediate_order: values.immediateDelivery, restaurant: { id: userProfile.id, }, farmer: { id: route.params.farmer.id, }, fk_order_items: cartProducts.map((product) => { const subtotal = (product.item.price - (product.item.price * (product.discount / 100))); const item_total = (product.item.price - (product.item.price * (product.discount / 100))) * product.quantity; return ( { product_id: product.item.id, stock_quantity: product.item.stock_quantity, name: product.item.name, unit_amount: product.item.amount, measurement: product.item.fk_unit_measurement?.name, images: product.item.images, quantity: product.quantity, price: product.item.price, discount: (product.item.price * (product.discount / 100)), subtotal, item_total, product_amount: product.item.amount * product.quantity, updated_product_amount: product.item.amount * product.quantity, updated_subtotal: subtotal, tax_rate: product.item.tax ? product.item.tax.tax_rate : farmer.fk_global_tax ? farmer.fk_global_tax.tax_rate : 0, is_refunded: false } ) }), fk_order_status: { id: 1 }, fk_shipping_address: { id: userProfile.fk_shipping_address.id }, fk_billing_address: { id: userProfile.fk_shipping_address.id } } getAxiosInstance(store).post(`/items/orders?fields=*.*.*`, orderData) .then((response) => { const orderDataResponse = response.data.data; const { fk_order_items, farmer, restaurant, id, delivery_date } = orderDataResponse; sendPushNotification( { to: userProfile.push_notification_key, title: `Bestellung #${id} wurde erstellt`, body: `Der Liefertermin ist: ${dayjs(delivery_date).format("DD.MM.YYYY")}`, data: null, }) // SEND TRANSACTIONAL EMAIL TO RESTAURANT sendEmail({ templateId: "DIRECTUS_RESTAURANT_Order_Confirmation", data: { total: values.immediateDelivery ? subTotal : (subTotal + farmer.delivery_fee), farmerFirstName: farmer.contact_first_name, restaurantFirstName: restaurant.contact_first_name, items: fk_order_items, vendor: farmer.store_name, orderNum: id, delivery_fee: farmer.delivery_fee, deliveryDate: dayjs(delivery_date).format("DD.MM.YYYY"), }, recipient: restaurant.contact_email, }); // SEND TRANSACTIONAL EMAIL TO FARMER sendEmail({ templateId: "DIRECTUS_FARMER_New_Order_Received", data: { total: values.immediateDelivery ? subTotal : (subTotal + farmer.delivery_fee), restaurant, items: fk_order_items, farmer, orderNum: id, delivery_fee: farmer.delivery_fee, deliveryDate: dayjs(delivery_date).format("DD.MM.YYYY"), }, recipient: farmer.contact_email, }); // LOWER STOCK AND EMPTY CART dispatch(createOrder(orderDataResponse, navigation)) trackAmplitudeEvent("Purchase", { total: values.immediateDelivery ? subTotal : (subTotal + farmer.delivery_fee), immediateDelivery: values.immediateDelivery }) dispatch(loadingStop()) }) .catch(error => { console.log(error, "ERROR CREATING ORDER"); dispatch(loadingStop()) }) } } const handleCallback = (values) => { const formattedDeliveryDate = values.deliveryDate; formattedDeliveryDate.setHours(0, 0, 0, 0) const today = new Date() const daysBefore = new Date(today) daysBefore.setDate(daysBefore.getDate() + cutoffOrderingDay) daysBefore.setHours(0, 0, 0, 0) //CHECK IF DELIVERY IS BEFORE CUTOFF TIME SPECIFIED BY VENDOR if (values.immediateDelivery) { Alert.alert( "Bist du sicher?", "Möchtest du direkt vor Ort (in deinem Restaurant oder auf dem Hof) bestellen?", [ { text: "Ja", onPress: () => { confirmSubmit(values) }, style: "default" }, { text: "Abbrechen", style: "cancel" } ] ) } else { confirmSubmit(values) } };
排查方向及可能原因
日期对象引用修改导致状态异常:
handleCallback中直接修改values.deliveryDate(formattedDeliveryDate = values.deliveryDate是引用赋值),会直接篡改Formik的表单状态,引发重渲染或流程阻塞。应改为创建新日期对象:const formattedDeliveryDate = new Date(values.deliveryDate);未捕获的静默异常:构建
orderData时可能存在属性未定义的情况(如farmer.delivery_fee、userProfile.fk_shipping_address.id),导致代码卡在数据构建阶段,未走到axios请求。建议给confirmSubmit添加全局try-catch,并在关键步骤打印日志,排查具体异常点。iCloud相关限制或冲突:同一iCloud账号设备出现相同问题,可能是iCloud隐私设置(如限制应用网络、跨设备跟踪)或iCloud Drive同步干扰了应用状态。可尝试让用户关闭该应用的iCloud Drive同步权限,或关闭设备的「跨设备跟踪」功能测试。
Loading状态逻辑异常:若
loading状态的redux处理存在问题,可能导致按钮闪烁。检查loadingStart和loadingStop的dispatch逻辑,确保所有分支都能正确停止loading。表单状态判断的隐性矛盾:
onSubmit仅判断shipping_address存在,但confirmSubmit额外判断userProfile.fk_shipping_address,若前者存在后者不存在,会弹出提示,但用户无反馈说明该情况未触发,需确认这两个值的一致性,或在onSubmit中提前做完整校验。
内容的提问来源于stack exchange,提问作者Eric Lehmann

