Problem explanation
I'm using Livewire with an abstract base component (AbstractRecipeList
) that handles common logic like render() and returns the same view (livewire.recipe-list
) for all child components.
Child components:
Each of them returns a different base query in getBaseQuery(), but they all use the same Blade view.
Each route loads the correct component, the recipes displayed are different for each route, livewire components work properly when loaded directly.
Issue
When navigating between pages like:
/users/profiles/1/liked
/users/profiles/1/saved
If I'll try to navigate from /recipes (route for FilteredRecipes.php
) to /users/profiles/1/liked I also don't have refresh
the URL updates, the data changes (recipes are different), but the component doesn't seem to re-render. No loading, no Livewire reset — just a silent switch in content.
What have I tried
Adding wire:key="...", but it didn't help me
Code:
AbsctractRecipeList.php:
abstract class AbstractRecipeList extends Component
{
use WithPagination;
public string $sort = 'popularity';
public function render()
{
$recipes = $this->getRecipes();
$recipes = $recipes->paginate(2)->withQueryString();
return view('livewire.recipe-list', [
'recipes' => $recipes
]);
}
abstract protected function getBaseQuery(): Builder;
protected function getRecipes(){
$query = $this->getBaseQuery()
->with(...)
->withCount(...);
return $this->applySorting($query);
}
public function applySorting($query)
{
return match ($this->sort){
'popularity' => $query->orderByDesc('savedCount')
// other cases
};
}
}
FilteredRecipes.php:
class FilteredRecipes extends AbstractRecipeList
{
public function mount(RecipeFilterRequest $request): void
{
// mount
}
public function getBaseQuery(): Builder
{
// Filter logic using URL parameters
$query = Recipe::when(...) // filter logic here
return $query;
}
}
SavedRecipes.php:
class SavedRecipes extends AbstractRecipeList
{
public function getBaseQuery(): Builder
{
return auth()->user()->savedRecipes()->getQuery();
}
}
LikedRecipes.php:
class LikedRecipes extends AbstractRecipeList
{
public function getBaseQuery(): Builder
{
return auth()->user()->likedRecipes()->getQuery();
}
}
And when I need to call those child components I am using:
<livewire:filtered-recipes />
<livewire:liked-recipes />
<livewire:saved-recipes />
Would be grateful for your help
Livewire treats components with the same view/DOM as identical, so it doesn't re-initialize on route change.
Fix: Add a dynamic wire:key
based on the route to force reload:
blade
<livewire:liked-recipes :wire:key="'liked-recipes-' . request()->path()" />
Or emit a custom event on route change and handle it in mount
or updated
to manually refresh the data.