ที่ผ่านมา ถ้าอยากให้หน้ารายละเอียดออเดอร์เปลี่ยนสถานะเองตอน job ตรวจสลิปทำงานเสร็จ เราก็มักใช้ usePoll() ให้หน้าเว็บถาม server ทุก 5 วินาที (แบบในโพสต์ Inertia 3.9) ก็ใช้ได้นะ แต่ request ส่วนใหญ่ได้คำตอบว่ายังเหมือนเดิม และสถานะใหม่ก็อาจมาช้าไปเกือบหนึ่งรอบ
live props ให้ server บอกหน้าเว็บเมื่อข้อมูลเปลี่ยน
live props กลับทิศกัน หน้าเว็บไม่ต้องถาม server คอยส่งสัญญาณผ่าน broadcasting ของ Laravel แทน browser เปิด WebSocket ค้างไว้กับ Reverb พอ job ทำงานเสร็จแล้ว broadcast event OrderUpdated ออกมา Inertia ที่ฟังอยู่ก็ขอเฉพาะ prop order ใหม่จาก controller ตัวเดิม (partial reload) เหมือนเรากดโหลดใหม่แค่ส่วนนั้นของหน้า

Inertia ขอข้อมูลใหม่เฉพาะตอนที่มี event มาถึง ไม่ต้องถามซ้ำตามรอบเวลา
ฝั่ง Laravel ประกาศ prop ด้วย Inertia::live()
ใน controller ห่อ prop ด้วย Inertia::live() แล้วบอกใน on: ว่าให้ฟัง event ตัวไหน Inertia อ่าน channel จาก broadcastOn() ของ event นั้นเอง เราไม่ต้องเขียนชื่อ channel ซ้ำ
use App\Events\OrderUpdated;
use Inertia\Inertia;
return Inertia::render('Orders/Show', [
'order' => Inertia::live(fn () => $order->fresh(), on: new OrderUpdated($order)),
]);
- ใช้คู่กับ prop แบบอื่นได้ ต่อ
->live()ท้ายInertia::defer(),once(),optional()หรือalways()ได้เลย ยกเว้น merge props ที่เป็น live ไม่ได้ ส่วน optional prop จะโหลดใหม่ก็ต่อเมื่อหน้าเคยโหลด prop นั้นมาแล้ว - ฟังหลาย event ส่งเป็น array เช่น
on: [new OrderUpdated($order), new OrderShipped($order)]prop ที่ฟัง event เดียวกันจะโหลดใหม่พร้อมกันใน request เดียว - เลือก channel เอง event ที่ broadcast ไปทั้ง
orders.1และordersจะทำให้ prop โหลดใหม่ทุกครั้งที่ออเดอร์ไหนก็ตามเปลี่ยน ถ้าอยากฟังแค่ช่องเดียว ใส่channel: new PrivateChannel('orders.1')เพิ่ม - ส่งชื่อ class แทน instance ได้ เช่น
on: OrderUpdated::classแต่ใช้ได้เฉพาะ event ที่ชื่อ channel ไม่ขึ้นกับข้อมูลข้างใน เพราะ Inertia สร้าง event ขึ้นมาโดยไม่เรียก constructor
private channel และ presence channel ใช้สิทธิ์ตามที่เขียนไว้ใน routes/channels.php เหมือนเดิม ไม่มีอะไรต้องตั้งเพิ่ม
ฝั่ง React ตั้ง transport ครั้งเดียวใน app.jsx
Inertia ต้องรู้ว่าจะฟัง event ผ่านอะไร เรียกว่า transport ถ้าตั้ง broadcasting ด้วย Reverb กับ Echo ไว้แล้ว ใส่ echo() ลงใน option live ของ createInertiaApp()
import { createInertiaApp } from '@inertiajs/react'
import { echo } from '@inertiajs/react/echo'
import { configureEcho } from '@laravel/echo-react'
configureEcho({ broadcaster: 'reverb' })
createInertiaApp({
live: echo(),
// ...
})
@laravel/echo-react เป็น optional peer dependency แอปที่ไม่ได้ใช้ live props จึงไม่ต้องลง ถ้าสร้าง Echo เองด้วย laravel-echo อยู่แล้ว ส่ง echo({ resolve: () => window.Echo }) แทนได้ Inertia จะ subscribe และเลิก subscribe channel ให้เองตอนผู้ใช้เปลี่ยนหน้า
ถ้าไม่ได้ใช้ Echo ก็ยังมี pusher() สำหรับ server ที่คุย protocol ของ Pusher ได้ (Reverb ก็นับด้วย) แต่ต้องตั้งสิทธิ์ของ channel ใน client เอง และมี actionCable() สำหรับฝั่ง Rails หรือจะเขียน transport เองจาก WebSocket ตัวอื่นหรือ server-sent events ก็ได้ ตามแบบในเอกสาร
Inertia กันไม่ให้ event ถี่ ๆ ยิง request ตาม
ถ้า event มาถี่ เช่นมีออเดอร์เข้าทีละหลายสิบรายการ การโหลดใหม่ทุกครั้งที่มี event ก็จะยิง request ถี่ตามไปด้วย Inertia จึงคุมไว้ให้ตั้งแต่แรก
| เรื่อง | Inertia ทำอะไร |
|---|---|
| ความถี่ | แต่ละ prop โหลดใหม่ได้ไม่เกินวินาทีละครั้ง event ที่มาระหว่างนั้นรวมเป็น request เดียวตอนครบเวลา ปรับได้ด้วย throttle (มิลลิวินาที) ทั้งที่ echo({ throttle: 2000 }) และราย prop |
| หลาย event จาก action เดียว | รอไม่กี่มิลลิวินาทีก่อนโหลด แล้วรวมทุก prop ที่โดนในครั้งนั้นเป็น request เดียว |
| แท็บอยู่เบื้องหลัง | หยุดโหลดจนกว่าผู้ใช้จะกลับมา ถ้าอยากให้โหลดต่อ ใส่ pauseWhenHidden: false |
| WebSocket หลุดแล้วต่อใหม่ | โหลดทุก live prop ใหม่ เพราะ event ที่ส่งมาตอนหลุดไม่มีทางมาถึง |
router.reload() ที่เราเรียกเองไม่โดน throttle
ส่งค่าใหม่ไปกับ event ได้ ถ้าทุกคนในช่องดูค่านั้นได้
ปกติแต่ละหน้าที่ฟังอยู่จะยิง request กลับมาขอค่าใหม่ ลองนึกถึง dashboard ที่เปิดค้างไว้ 1,000 แท็บ event เดียวจะกลายเป็น 1,000 request ทันที ทางแก้คือใส่ค่าใหม่ไปกับ event เลยด้วย Inertia::broadcastProps() แล้ว Inertia จะเขียนค่านั้นลงหน้าโดยไม่ขอ server อีก
public function broadcastWith(): array
{
return [
'order_id' => $this->order->id,
...Inertia::broadcastProps([
'order' => OrderResource::make($this->order),
]),
];
}
ของเล็ก ๆ ที่มาพร้อม live props
useProp('order')คืนvalueพร้อมloadingระหว่างที่ prop กำลังโหลดใหม่ เอาไปทำหน้าจางลงนิดหนึ่งให้ผู้ใช้รู้ว่ากำลังอัปเดต และมีloadedสำหรับ prop ที่เป็นทั้ง deferred และ live- event
liveของ router ยิงก่อนอัปเดต prop และยกเลิกได้ด้วยการคืนfalseเช่นหน้าที่ผู้ใช้กำลังกรอกฟอร์มอยู่ อาจขึ้นปุ่ม "มีข้อมูลใหม่" ให้กดเองแทนการเปลี่ยนหน้าจอใต้มือผู้ใช้ toOthers()ใช้ได้เลย Inertia ส่ง headerX-Socket-Idไปกับ request ที่อยู่ origin เดียวกันbroadcast(new OrderUpdated($order))->toOthers()จึงไม่ส่ง event กลับมาหาคนที่เพิ่งกดบันทึก
usePoll ยังเหมาะกับเว็บบน shared hosting
live props ต้องมีสองอย่างรันค้างอยู่บนเซิร์ฟเวอร์ตลอด คือ Reverb (หรือบริการอย่าง Pusher) กับ queue worker ที่ส่ง event ออกไป ถ้าเว็บอยู่บน shared hosting ที่ใช้ cPanel หรือ DirectAdmin ซึ่งรัน process ค้างไม่ได้ usePoll() กับ background: 'pause' ยังเป็นทางที่ง่ายกว่า ส่วนเว็บที่อยู่บน VPS อยู่แล้ว live props ช่วยลด request ที่ไม่จำเป็นได้เยอะ และหน้าจอก็เปลี่ยนทันทีที่ข้อมูลเปลี่ยน
อัปเดตทั้งสองฝั่งพร้อมกัน
composer require inertiajs/inertia-laravel:^3.7
npm install @inertiajs/react@^3.11 @laravel/echo-react
รายละเอียดทั้งหมดอยู่ในบทความต้นฉบับ option ครบทุกตัวและวิธีเขียน transport เองอยู่ในเอกสาร Live Props ส่วนรายการเปลี่ยนแปลงอยู่ใน release notes ของ v3.11.0






