Merge pull request #16340 from filamentphp/fix-state-dehydration

fix: State dehydration with non-unique fields
This commit is contained in:
Dan Harrin
2025-05-27 19:43:59 +01:00
committed by GitHub
3 changed files with 103 additions and 4 deletions
@@ -170,7 +170,17 @@ trait HasState
{
if (! ($isDehydrated && $this->isDehydrated())) {
if ($this->hasStatePath()) {
Arr::forget($state, $this->getStatePath());
$rootContainer = $this->getContainer();
while (! $rootContainer->isRoot()) {
$rootContainer = $rootContainer->getParentComponent()->getContainer();
}
$statePath = $this->getStatePath();
if (! $rootContainer->hasDehydratedComponent($statePath)) {
Arr::forget($state, $statePath);
}
return;
}
+21
View File
@@ -78,6 +78,27 @@ trait HasState
return $state;
}
public function hasDehydratedComponent(string $statePath): bool
{
foreach ($this->getComponents(withHidden: true) as $component) {
if (! $component->isDehydrated()) {
continue;
}
if ($component->hasStatePath() && ($component->getStatePath() === $statePath)) {
return true;
}
foreach ($component->getChildComponentContainers(withHidden: true) as $container) {
if ($container->hasDehydratedComponent($statePath)) {
return true;
}
}
}
return false;
}
/**
* @param array<string, mixed> $state
* @return array<string, mixed>
+71 -3
View File
@@ -486,7 +486,7 @@ test('hidden components are excluded from state dehydration except if they are m
->fill();
expect($container)
->dehydrateState()->not()->toBe([]);
->dehydrateState()->data->not()->toBe([]);
$container = ComponentContainer::make(Livewire::make())
->statePath('data')
@@ -505,7 +505,7 @@ test('hidden components are excluded from state dehydration except if they are m
->fill();
expect($container)
->dehydrateState()->not()->toBe([]);
->dehydrateState()->data->not()->toBe([]);
});
test('hidden components are excluded from state dehydration even if their parent component has a state path', function () {
@@ -531,6 +531,74 @@ test('hidden components are excluded from state dehydration even if their parent
]);
});
test('components are not excluded from state dehydration if there is another dehydrated field with the same name', function () {
$container = ComponentContainer::make(Livewire::make())
->statePath('data')
->components([
(new Component)
->statePath($statePath = Str::random())
->default(Str::random())
->dehydrated(false),
(new Component)
->statePath($statePath)
->default(Str::random()),
])
->fill();
expect($container)
->dehydrateState()->data->not()->toBe([]);
$container = ComponentContainer::make(Livewire::make())
->statePath('data')
->components([
(new Component)
->statePath($statePath = Str::random())
->default(Str::random()),
(new Component)
->statePath($statePath)
->default(Str::random())
->dehydrated(false),
])
->fill();
expect($container)
->dehydrateState()->data->not()->toBe([]);
});
test('hidden components are not excluded from state dehydration if there is another visible field with the same name', function () {
$container = ComponentContainer::make(Livewire::make())
->statePath('data')
->components([
(new Component)
->statePath($statePath = Str::random())
->default(Str::random())
->hidden(),
(new Component)
->statePath($statePath)
->default(Str::random()),
])
->fill();
expect($container)
->dehydrateState()->data->not()->toBe([]);
$container = ComponentContainer::make(Livewire::make())
->statePath('data')
->components([
(new Component)
->statePath($statePath = Str::random())
->default(Str::random()),
(new Component)
->statePath($statePath)
->default(Str::random())
->hidden(),
])
->fill();
expect($container)
->dehydrateState()->data->not()->toBe([]);
});
test('disabled components are excluded from state dehydration', function () {
$container = ComponentContainer::make(Livewire::make())
->statePath('data')
@@ -577,7 +645,7 @@ test('disabled components are excluded from state dehydration except if they are
->fill();
expect($container)
->dehydrateState()->not()->toBe([]);
->dehydrateState()->data->not()->toBe([]);
});
test('disabled components are excluded from state dehydration if their parent component is disabled and not marked as dehydrated', function () {