usePoll หยุดได้ตอนผู้ใช้สลับไปแท็บอื่น
polling คือให้หน้าเว็บขอข้อมูลจาก server ใหม่ทุก ๆ กี่วินาที ใช้กับหน้าที่ต้องเห็นของใหม่โดยไม่ต้องกด refresh เช่นหน้ารายการออเดอร์ dashboard ยอดขาย หรือหน้ารอผลตรวจสลิปที่ตรวจอยู่ใน queue (แบบในโพสต์ตรวจสอบสลิปโอนเงินผ่าน SlipOK) ใน Inertia เขียนแค่บรรทัดเดียว
import { usePoll } from '@inertiajs/react'
export default function Index({ orders }) {
usePoll(5000, { only: ['orders'] })
// ...
}
ที่ผ่านมา ถ้าผู้ใช้สลับไปแท็บอื่น Inertia จะลดความถี่ลง 90% คือยิงทุกรอบที่ 10 แทน ถ้าอยากให้ยิงเต็มความถี่ก็ใส่ keepAlive: true แต่ไม่มีทางสั่งให้หยุดไปเลย
ใน 3.9 มี option background ให้เลือกสามแบบ
| ค่า | แท็บอยู่เบื้องหลังแล้วทำอะไร |
|---|---|
'throttle' |
ยิงทุกรอบที่ 10 เหมือนเดิม (ค่าเริ่มต้น) |
'pause' |
หยุดยิงจนกว่าผู้ใช้จะกลับมาที่แท็บนี้ |
'continue' |
ยิงเต็มความถี่ต่อไป ใช้แทน keepAlive: true ที่เลิกแนะนำแล้ว |
usePoll(5000, { only: ['orders'] }, { background: 'pause' })
ตอนผู้ใช้กลับมาที่แท็บ ถ้าระหว่างที่หยุดไปถึงรอบที่ต้องยิงแล้ว Inertia ยิงทันที ไม่อย่างนั้นก็รอให้ครบรอบที่เหลือ หน้าจอจึงไม่ค้างข้อมูลเก่าตอนกลับมาดู
ลองคิดเป็นตัวเลขดู poll ทุก 5 วินาทีคือชั่วโมงละ 720 request ต่อหนึ่งแท็บ แบบ throttle เหลือ 72 ส่วน pause เป็นศูนย์ ถ้าแอปอยู่บน shared hosting หรือ VPS ตัวเล็ก แล้วพนักงานเปิดหน้า dashboard ทิ้งไว้ทั้งวันหลายแท็บ pause ช่วยได้เยอะ
ส่วน continue เหมาะกับหน้าที่ต้องทำงานแม้ไม่มีใครดู อย่างแท็บรับออเดอร์ที่ร้านเปิดทิ้งไว้แล้วให้เล่นเสียงเตือนตอนมีออเดอร์ใหม่ ถ้าโค้ดเดิมใช้ keepAlive: true อยู่ เปลี่ยนเป็น background: 'continue' ได้เลย ความหมายเท่ากัน
navigate event บอกได้แล้วว่าผู้ใช้กดย้อนกลับ
ตอนผู้ใช้กดปุ่ม back หรือ forward ของ browser Inertia ไม่ได้ขอหน้าจาก server ใหม่ แต่เอาหน้าเดิมกลับมาจาก history พร้อม props ชุดที่มีตอนผู้ใช้ออกจากหน้านั้น ถ้าออกไปนานแล้ว ข้อมูลก็อาจเก่า เช่นกลับมาที่รายการออเดอร์แล้วยังเห็นสถานะเดิม ทั้งที่ออเดอร์เพิ่งเปลี่ยนสถานะไปจากหน้ารายละเอียด
3.9 เพิ่ม type ใน event navigate ให้แยกได้แล้ว
initialเปิดหน้าครั้งแรก หรือกด refreshvisitไปหน้าใหม่ตามปกติ เช่นคลิก<Link>historyกลับมาจากปุ่ม back หรือ forward
เราจึงโหลดเฉพาะ props ที่อาจเก่าใหม่ได้ ตอนที่กลับมาจาก history เท่านั้น
import { router } from '@inertiajs/react'
router.on('navigate', (event) => {
const { type, page } = event.detail
if (type === 'history' && page.component === 'Orders/Index') {
router.reload({ only: ['orders'] })
}
})
ใส่ไว้ใน app.jsx จะได้รับทุก event ตั้งแต่หน้าแรก only ช่วยให้ server ส่งกลับมาแค่ props ที่ขอ ไม่ต้อง query ทั้งหน้าใหม่
ออกจากระบบแล้ว ล้าง prefetch cache ให้ด้วย
Inertia มีสองอย่างที่เก็บหน้าไว้ใน browser อย่างแรกคือ prefetch ถ้าใส่ <Link prefetch> Inertia จะโหลดหน้าปลายทางไว้ก่อนผู้ใช้คลิก แล้วเก็บไว้ใน cache สักพัก อย่างที่สองคือ history ที่เก็บ props ของทุกหน้าที่ผ่านมา ซึ่งเข้ารหัสไว้ได้ และตอนออกจากระบบเราเรียก Inertia::clearHistory() ให้เปลี่ยนกุญแจ history เก่าจะอ่านไม่ได้อีก
ปัญหาคือก่อน 3.9 clearHistory() ไม่ได้ล้าง prefetch cache ไปด้วย หน้าที่ต้อง login ซึ่งเคย prefetch ไว้จึงยังโผล่ขึ้นมาได้ตอนกดย้อนกลับหลังออกจากระบบ ตอนนี้ล้างให้แล้ว ทั้งตอน response จาก server มี clearHistory และตอนเรียก router.clearHistory() ฝั่ง browser request prefetch ที่ยังวิ่งอยู่ตอนล้างก็จะไม่ลง cache อีก
ฝั่ง Laravel เรียกไว้ใน controller ที่ logout ได้เลย
public function destroy(Request $request): RedirectResponse
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
Inertia::clearHistory();
return redirect('/');
}
แก้บั๊กปุ่มย้อนกลับกับ InfiniteScroll
ส่วนที่เหลือเป็นการแก้บั๊ก อัปเดตแล้วได้เลยไม่ต้องแก้โค้ด
- ถ้า deferred props, poll หรือ partial reload ตอบกลับมาตอนผู้ใช้กำลังกดย้อนกลับ เดิม response นั้นจะทับหน้าที่เพิ่งเอากลับมาจาก history ตอนนี้ไม่ทับแล้ว
useRememberไม่เอา state ของหน้าก่อน ๆ มาใส่ผิดหน้าแล้ว<InfiniteScroll>ยกเลิก request ที่ยังค้างอยู่ตอนผู้ใช้เปลี่ยนหน้า ไม่มี error จาก callback ที่ทำงานหลัง component หายไปแล้ว
รายละเอียดทั้งหมดอยู่ในบทความต้นฉบับ และใน release notes ของ Inertia v3.9.0 ที่ลิงก์ไปยังแต่ละ PR ส่วน option ทั้งหมดของ usePoll ดูได้ในเอกสาร Polling






