
LivewireとjQueryを併用してつまずいたこと
はじめに
少し前にLivewireを使う機会がありました。便利な反面、癖があり慣れるのに中々苦労しています。
そんな中、何故かLivewireで更新したコンポーネントのdata属性を取得すると古い値のままになっている事象に遭遇しました。解決に時間が掛かったので、今回は解決方法を共有したいと思います。
結論から言うと原因はLivewireではなく、jQueryのdata()の仕様でした。
環境
- Laravel v11.16.0
- Livewire v3.5.6
- jQuery v3.7.1
サンプルコード
コンポーネントのクラス
<?php
declare(strict_types=1);
namespace App\Livewire;
use Illuminate\Contracts\View\View;
use Livewire\Component;
class Counter extends Component
{
public int $count = 1;
public function increment(): void
{
$this->count++;
}
public function render(): View
{
return view('livewire.counter');
}
}
コンポーネントのビュー
<div>
<button id="countButton" data-count="{{$count}}" wire:click="increment">カウントアップ</button>
</div>
@script
<script>
Livewire.hook("commit", ({component, succeed}) => {
succeed(() => {
if (component.name === 'counter') {
const count = $('#countButton').data('count');
console.log(count);
}
});
});
</script>
@endscript
ボタン3回押下後のコンソール出力
1、2、3と出力されるはずが全て1になっています。
1
1
1
ここでLivewireの問題かと思い、色々調べましたが、結局jQueryのdata()の仕様の問題で、data()は初回に呼び出した際の値を保持して、その後、値は変更されないようです。
Since jQuery 1.4.3, data-* attributes are used to initialize jQuery data. An element’s data-* attributes are retrieved the first time the data() method is invoked upon it, and then are no longer accessed or mutated (all values are stored internally by jQuery).
.data() | jQuery API Documentation
なので今回はjQueryのdata()は使わずにdata属性の値を取得するように変更したら解決しました。
コンポーネントのビュー(変更後)
// 変更前
// const count = $('#countButton').data('count');
// 変更後
const count = document.querySelector('#countButton').dataset.count;
ボタン3回押下後のコンソール出力
意図した通り1、2、3と出力されるようになりました。
1
2
3
おわりに
まさかjQueryのdata()に初回に取得した値は以降変更が反映されない仕様があるとは思わず、Livewire側に問題があると決めつけてしまい、原因に気づくまでに時間を要してしまいました。
今回の経験は不具合の原因を調査する際に特定の技術や要素に視野が偏らないよう注意することの大切さを気付かせてくれる良い教訓となりました。
この記事が類似の事象に遭遇した方のお役に立てれば幸いです。