การปัดรายการบน Mobile
เอกสารนี้สรุปเคสที่เจอบ่อยใน React Native list: ปัดรายการแล้วเห็นปุ่ม action แต่กดปุ่มแล้วไม่มีอะไรเกิดขึ้น
อาการ
- ปัด row แล้วเห็นปุ่ม action
- log ใน
renderLeftActionsหรือrenderRightActionsออก - log ใน
onPressของปุ่ม action ไม่ออก - อาการดูเหมือน permission หรือ business rule ผิด แต่จริง ๆ press event ไปไม่ถึงปุ่ม
สาเหตุ
SwipeableFlashList วางปุ่ม action ไว้ด้านหลัง card แล้วขยับ card ด้วย translateX
ถ้า layer ของ card ยังสูงกว่า action area อยู่ จะเกิดเคสที่เห็นปุ่มแล้ว แต่พื้นที่ tap ยังถูก card layer กินอยู่ ใน repo นี้ itemContent มี zIndex: 1 อยู่แล้ว ดังนั้น action layer ต้องถูกยกขึ้นให้สูงกว่า card
วิธีแก้
ใน apps/mobile/src/components/SwipeableFlashList/index.tsx:
- ใส่
pointerEvents="box-none"ที่ wrapper ของ action และ inner action content - ให้ action wrapper เป็น
pointerEvents="none"จนกว่า row จะถูกเปิดจาก swipe จริง ไม่อย่างนั้นปุ่มที่ยังมองไม่เห็นอาจกดได้ก่อน swipe - ใส่
zIndexและelevationให้leftActionsและrightActionsสูงกว่าitemContent - ถ้าต้อง debug disabled state ให้
Pressableยังรับ tap ได้ แล้วค่อยเรียกconfig.onPress?.()แบบมีเงื่อนไข
โครง action layer ที่ควรใช้:
<Animated.View
pointerEvents={actionsTouchable ? 'box-none' : 'none'}
style={[styles.leftActions, leftActionStyle]}
>
<View pointerEvents="box-none" style={styles.actionContent}>
{leftActions}
</View>
</Animated.View>
ตั้ง actionsTouchable เป็น true เฉพาะตอน pan gesture ตัดสินใจเปิด row แล้ว และตั้งกลับเป็น false เมื่อ close/reset วิธีนี้กันไม่ให้ปุ่ม action ที่ยังมองไม่เห็นถูกกดได้ แต่ยังให้ปุ่มที่เปิดจาก swipe แล้วกดได้ปกติ
style ที่ควรมี:
leftActions: {
...StyleSheet.absoluteFill,
zIndex: 2,
elevation: 2,
},
rightActions: {
...StyleSheet.absoluteFill,
zIndex: 2,
elevation: 2,
},
itemContent: {
width: '100%',
zIndex: 1,
},
Checklist เวลาดีบัก
- ใส่ log ใน
renderLeftActionsและrenderRightActions - ใส่ log ใน
onPressของPressable - ถ้า render log ออก แต่ press log ไม่ออก ให้ตรวจ layer ของ swipe action ก่อนตรวจ permission
- เช็ค direction ของ swipe:
leftActionsเปิดเมื่อ “ลาก row ไปทางขวา”rightActionsเปิดเมื่อ “ลาก row ไปทางซ้าย”
- ถ้า action เป็น disabled-looking state แต่ต้องการ debug ให้คง
Pressableไว้ แล้วเรียกconfig.onPress?.()เฉพาะตอนมี action จริง
ตัวอย่างจาก Invoice
invoiceListScreen ใช้ pattern นี้กับปุ่มยกเลิกใบแจ้งหนี้ log ที่ควรเห็นคือ:
[InvoiceListScreen] cancel swipe render[InvoiceListScreen] swipe action press[InvoiceListScreen] cancel swipe press
เวลาเช็คเจ้าของเอกสารให้ log ทั้ง:
loginUserCodeinvoiceUserCoderawInvoiceUserCode
ก่อนเทียบ owner ต้อง normalize user code เพราะ API อาจส่งเลขที่ไม่มี 0 นำหน้า เช่น 12265 แต่ user login เป็น 012265 ซึ่งต้องถือว่าเป็น user เดียวกัน