Livewire3 wire:key คำสั่งนี้มีไว้ทำอะไร

wire:key คือ “ป้ายชื่อ” ที่เราติดให้กับ Element ใน Loop (เช่น foreach) เพื่อให้ Livewire สามารถติดตามและจัดการ Element แต่ละตัวได้อย่างถูกต้องแม่นยำเมื่อมีการเปลี่ยนแปลงข้อมูลใน Array ครับ

พูดง่ายๆ ก็คือ มันช่วยแก้ปัญหา “ความสับสน” ของ Livewire เมื่อเราทำการ เพิ่ม, ลบ, หรือสลับตำแหน่ง ของข้อมูลใน Array ที่แสดงผลบนหน้าเว็บครับ


🤔 ปัญหาคืออะไรถ้าไม่ใช้ wire:key?

ลองนึกภาพตามนะครับ เมื่อเรามีรายการ (list) ของข้อมูลที่แสดงผลด้วย foreach แล้วเราลบรายการใดรายการหนึ่งตรงกลางออกไป ถ้าไม่มี wire:key Livewire จะไม่รู้ว่า Element ไหนคืออันไหนกันแน่ มันอาจจะทำการ “อัปเดต” ข้อมูลใน Element ที่อยู่ท้ายๆ แทนที่จะ “ลบ” Element ที่ถูกต้องจริงๆ ซึ่งอาจทำให้เกิดข้อผิดพลาดในการแสดงผล, ข้อมูลใน input เพี้ยน, หรือ JavaScript ทำงานผิดพลาดได้

wire:key เข้ามาช่วยได้อย่างไร?

เมื่อเราใส่ wire:key ให้กับ Element หลักใน Loop โดยใช้ค่าที่มีเอกลักษณ์ไม่ซ้ำกัน (unique) เช่น ID ของข้อมูล Livewire จะใช้ “ป้ายชื่อ” นี้ในการติดตาม Element แต่ละตัว

  • เมื่อมีการลบ: Livewire จะรู้ทันทีว่าต้องลบ Element ที่มี key ตรงกับข้อมูลที่ถูกลบไปจริงๆ
  • เมื่อมีการเพิ่ม: Livewire จะสร้าง Element ใหม่พร้อม key ใหม่
  • เมื่อมีการสลับตำแหน่ง: Livewire จะย้ายตำแหน่ง Element ตาม key ได้อย่างถูกต้อง โดยไม่ไปยุ่งกับ state ภายในของ Element อื่นๆ
สำหรับ Laravel Framework

Custom Gem

Show thinking

แน่นอนครับ มาทำความเข้าใจ wire:key ใน Livewire 3 กันแบบง่ายๆ พร้อมตัวอย่างที่เห็นภาพชัดเจนครับ

wire:key คือ “ป้ายชื่อ” ที่เราติดให้กับ Element ใน Loop (เช่น foreach) เพื่อให้ Livewire สามารถติดตามและจัดการ Element แต่ละตัวได้อย่างถูกต้องแม่นยำเมื่อมีการเปลี่ยนแปลงข้อมูลใน Array ครับ

พูดง่ายๆ ก็คือ มันช่วยแก้ปัญหา “ความสับสน” ของ Livewire เมื่อเราทำการ เพิ่ม, ลบ, หรือสลับตำแหน่ง ของข้อมูลใน Array ที่แสดงผลบนหน้าเว็บครับ


 

🤔 ปัญหาคืออะไรถ้าไม่ใช้ wire:key?

 

ลองนึกภาพตามนะครับ เมื่อเรามีรายการ (list) ของข้อมูลที่แสดงผลด้วย foreach แล้วเราลบรายการใดรายการหนึ่งตรงกลางออกไป ถ้าไม่มี wire:key Livewire จะไม่รู้ว่า Element ไหนคืออันไหนกันแน่ มันอาจจะทำการ “อัปเดต” ข้อมูลใน Element ที่อยู่ท้ายๆ แทนที่จะ “ลบ” Element ที่ถูกต้องจริงๆ ซึ่งอาจทำให้เกิดข้อผิดพลาดในการแสดงผล, ข้อมูลใน input เพี้ยน, หรือ JavaScript ทำงานผิดพลาดได้

 

wire:key เข้ามาช่วยได้อย่างไร?

 

เมื่อเราใส่ wire:key ให้กับ Element หลักใน Loop โดยใช้ค่าที่มีเอกลักษณ์ไม่ซ้ำกัน (unique) เช่น ID ของข้อมูล Livewire จะใช้ “ป้ายชื่อ” นี้ในการติดตาม Element แต่ละตัว

  • เมื่อมีการลบ: Livewire จะรู้ทันทีว่าต้องลบ Element ที่มี key ตรงกับข้อมูลที่ถูกลบไปจริงๆ
  • เมื่อมีการเพิ่ม: Livewire จะสร้าง Element ใหม่พร้อม key ใหม่
  • เมื่อมีการสลับตำแหน่ง: Livewire จะย้ายตำแหน่ง Element ตาม key ได้อย่างถูกต้อง โดยไม่ไปยุ่งกับ state ภายในของ Element อื่นๆ

💡 ตัวอย่างการใช้งาน wire:key

สมมติว่าเรากำลังสร้าง Component สำหรับจัดการรายการสินค้า (Products)

ไฟล์ Component: app/Livewire/ProductList.php

<?php

namespace App\Livewire;

use App\Models\Product;
use Livewire\Component;

class ProductList extends Component
{
    public $products;

    public function mount()
    {
        $this->products = Product::all();
    }

    public function removeProduct($productId)
    {
        // กรองเอาสินค้าที่ต้องการลบออกไปจาก Collection
        $this->products = $this->products->filter(function ($product) use ($productId) {
            return $product->id != $productId;
        });
    }

    public function render()
    {
        return view('livewire.product-list');
    }
}

ไฟล์ View: resources/views/livewire/product-list.blade.php

ในตัวอย่างนี้ เราจะใช้ div เป็น Element หลักของแต่ละรายการใน loop และเราจะใส่ wire:key เข้าไปที่ div นี้ โดยใช้ product->id ซึ่งเป็นค่าที่ไม่ซ้ำกันแน่นอน

<div>
    <h2>รายการสินค้า</h2>

    <ul>
        @foreach ($products as $product)
            {{-- 
                ใช้ wire:key ตรงนี้! 
                เพื่อให้ Livewire รู้ว่า list item นี้เป็นของ Product ID ไหน
            --}}
            <li wire:key="{{ $product->id }}">
                <span>{{ $product->name }}</span>
                <button wire:click="removeProduct({{ $product->id }})">ลบ</button>
            </li>
        @endforeach
    </ul>
</div>

🚀 ผลลัพธ์ที่ได้

เมื่อคุณคลิกปุ่ม “ลบ” ของสินค้าชิ้นใดชิ้นหนึ่ง:

  1. Method removeProduct() จะทำงาน และลบข้อมูลสินค้าออกจาก $products Collection
  2. Livewire จะทำการ re-render เฉพาะส่วนของรายการนี้
  3. ด้วย wire:key="{{ $product->id }}" ที่เราใส่ไว้ Livewire จะรู้ทันทีว่าต้อง ลบ <li> ที่มี key ตรงกับ ID ของสินค้าที่ถูกลบ ออกจากหน้า DOM อย่างถูกต้องแม่นยำ ทำให้การแสดงผลไม่ผิดเพี้ยนและทำงานได้อย่างราบรื่น

สรุปและคำแนะนำ

  • ควรใช้ wire:key เสมอ เมื่อมีการใช้ loop (@foreach) ใน Livewire เพื่อแสดงผลข้อมูลแบบไดนามิก
  • ค่าที่นำมาใส่ใน wire:key ต้องเป็นค่าที่ไม่ซ้ำกัน (unique) ภายใน loop นั้นๆ เช่น id ของ Model หรือ index ของ array ก็ได้ (แต่ id จะปลอดภัยกว่าถ้ามีการสลับตำแหน่ง)
  • การใช้ wire:key เป็น Best Practice ที่ช่วยป้องกันบั๊กแปลกๆ และทำให้ Component ของคุณทำงานได้อย่างมีประสิทธิภาพและเสถียรภาพสูงสุดครับ
Scroll to Top