当尝试为...组件进行数据注入时,Livewire遇到了损坏的数据。

15

我遇到了以下错误,但是有点摸不着头脑:

Livewire 尝试重新启动组件时遇到损坏的数据。请确保 Livewire 组件的 [name、id、data] 在请求之间没有被篡改。

情况如下:使用 Livewire 2.x、Laravel 7.x,在组件控制器中从 3 个 MySQL 存储过程中获取数据并处理。组件 Blade 是一个相当基本的 Blade,其中包含 foreach 循环。我正在使用 wire:init 功能,以便组件不会阻塞页面加载。它包含一个自定义的分页功能。切换到第二页数据时,出现此错误。在 Livewire 1.x 上没有发生错误。

有人知道如何解决这个问题吗?这个错误本身对我来说并没有多少意义。需要补充其他信息吗?

先提前感谢您的帮助!

20个回答

39
在我的情况下,解决方案是将一个公共属性变为受保护的,并手动将其传递给 Blade,以便在幕后排除 Livewire 的自动处理。

10
最佳答案!Livewire仍然存在问题,无法重新注入具有不同值的相同属性。例如,如果您有一个集合,然后更改为分组集合。谢谢Markus。 - Eric Lagarda
3
这个答案救了我的生命 :) 谢谢。 - Sinan Eldem
@EricLagarda 你应该将这个评论添加为答案。它解决了我的问题并且是完全有效的答案。 - brenjt
对我来说是有效的答案! - Leo
在我的情况下,一些公共属性在“updatedProperty”钩子中被更新,这让我很难追踪。因此,如果您不知道确切的问题来源,请检查更新/已更新的钩子。 - Marian
如果你需要在后续请求中跟踪你的$protectedProperty,那么你也可以将该属性传递给你的方法,像这样:wire:click="add(@js($protectedProperty))" - Lenor

15

要解决这个问题,请打开vendor/livewire/livewire/src/ComponentChecksumManager.php文件,在第19行的返回语句之前添加var_dump($stringForHashing);。然后,您可以查看被哈希的数据并将其与先前哈希的数据进行比较,以找到差异。

在我这样做之后,我能够识别出JavaScript正在重新排列的数字键,并想出了一个适当的修复方法。

需要注意的一点是,某些JSON格式化程序也会重新排序数字键,因此最好不要格式化JSON或手动格式化它以进行比较。

编辑: 使用var_dump可能会干扰某些页面的功能,因此将数据写入文件可能是更好的选择:

file_put_contents('/path/to/log.txt', $stringForHashing . "\n\n", FILE_APPEND);

谢谢,这真的帮了我很多。 - Matthew Bowen
非常有用,如果能在LW中使用就太棒了。 - digout
这也对我有帮助!非常有用的建议。 - prikkprikkprikk

7

就我们遇到的问题而言,它是一个非常大的整数,比javascript的Number.MAX_SAFE_INTEGER所能处理的要大。

我们在这里提交了一个错误报告:https://github.com/livewire/livewire/discussions/4788(livewire 2.10.4)。

因此,当使用过大的整数时,该错误本身没有解决方法。如果你想将你的值作为真正的整数来处理,暂时还没有办法,但是将其转换为字符串可能适用于你(并且/或者在php端进行计算——使用protected属性——如果在你的情况下可行)。

话虽如此,我们遇到问题的真正原因是将uuid转换为int,因为我们没有填写我们的laravel模型的protected $keyType = 'string';https://laravel.com/docs/9.x/eloquent#primary-keys)!


1
谢谢!我一直在使用kra8/laravel-snowflake实现的雪花算法,完全忘记了关于JavaScript最大整数的警告。 - ainesophaur
过去两天我一直在苦苦思索,幸运的是终于找到了答案。当我使用一个由17位数字组成的整数时,我遇到了这个异常。这应该至少被记录下来。 - bakis
1
感谢 @user2341627 指出这个问题,正是我遇到的问题,我的 ID 太大了,直到我在模型的 casts 属性中加入 'id' => 'string' 才解决了。现在可以正常工作了。 - Peter Fox

4
我运行了以下命令,问题得到解决: php artisan optimize

1
这对我解决了问题。 - Geovane Krüger

1
除了其他人上面建议的内容之外,如果您有一个使用groupBy()的集合,这也可能是此问题的原因。
要解决此问题,请在组件中使用protected $attribute而不是public,然后将$attribute传递给组件视图。
protected $attribute;

public function mount($attribute){
   $this->attribute = $attribute;
}

...........

public function render()
{
    return view('livewire.view-here',['attribute'=>$attribute]);
}

0
在我的情况下,问题来自于数据库查询和结果集合。这个查询(变量的含义并不重要)
DB::table('progress_trackings')
        ->select('user_id')
        ->whereIn('user_id', $users->pluck('id'))
        ->where('object_id', $activity->id)
        ->where('event', $type)
        ->get()
        ->keyBy('user_id');

生成了这个输出:

Illuminate\Support\Collection {#2427
 all: [
   454 => {#2279
     +"user_id": 454,
   },
   528 => {#441
     +"user_id": 528,
   },
   531 => {#2368
     +"user_id": 531,
   },
 ],

查询是由 Blade 文件中的按钮触发的。 点击 2 或 3 次按钮会导致 hydration 错误。

在 Livewire 文档中解释了数组键有时可能会引起问题:https://laravel-livewire.com/docs/2.x/troubleshooting

因此,我尝试将数据库查询结果转换为简单的数组。由于我只需要键,所以这个方法可行:

DB::table('progress_trackings')
    ->select('user_id')
    ->whereIn('user_id', $users->pluck('id'))
    ->where('object_id', $activity->id)
    ->where('event', $type)
    ->get()
    ->keyBy('user_id')
    ->keys()->toArray(); // ADDED THIS

现在的结果是:

[
 454,
 528,
 531,

]

解决了hydration错误。


0
在我的情况下,我有几个公共变量,并不是所有的变量都从父视图中传递过来。在阅读了Markus的答案之后,我添加了mount方法到我的livewire类中,并传入了我从父类继承的变量,然后它就可以工作了。我正在使用Livewire 2.3。
这个出现了错误。
class MyView extends Component
{
  public $fromParent, $local;

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

添加挂载点解决了问题

class MyView extends Component
{
  public $fromParent, $localVariable1, localVariable2;

  public function mount($fromParent)
  {
    $this->fromParent = $fromParent;
  }

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

0

看起来,有一些公共变量已经被设置或未设置(由您的代码填充值或为空)使用任何Livewire Hook方法。

请检查这些并修复它们,在生命周期钩子方法调用期间,这些值未正确设置或未设置,我也遇到了这个问题并解决了它。

在我的情况下,在updated钩子方法中,我进行了更改

这个

$this->{'selectGroup.'.$value} = false;

$this->selectGroup[$value] = false;

对我来说效果很好,希望它能有意义。


0
在我的情况下,我正在尝试为API获取完整的图像链接,这是我在模型中的错误。
public function getImageAttribute($value)
{ 
   return  $value ? url(Storage::url($value)) : ''; 
}

这导致 Livewire 遇到了损坏的数据..

在我的情况下,解决方案是

 public function getImageAttribute($value)
{
    if (Str::contains(Request()->route()->getPrefix(), 'api')) {
        return  $value ? url(Storage::url($value)) : '';
    }
    return $value;
}

0
在我的情况下,我有另一个组件中受影响的livewire组件。
//livewire component
<x-layouts.content-nosidebar title="false">
     <div class="verification section-padding">
     </div>
</x-layouts.content-nosidebar>

我将livewire组件移动到它自己的文件中,然后就不再出现错误了。

//livewire component
<div class="verification section-padding">
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接