How can I prevent my Livewire component from reloading every time the page refreshes? I placed the component in the resources\views\layouts\app.blade.php file. This component is responsible for loading categories, and I want it to appear on every page, which is why I placed it there.
I also have a Product Livewire component and a Product Detail Livewire component. Does anyone have any ideas on how I can prevent the component from reloading? Thanks in advance for your help.
In the config\livewire.php file, I set the layout as follows:
'layout' => 'layouts.app',
I include it in the app.blade.php file like this:
@livewire('category-navigation')
resources\views\layouts\app.blade.php
<main>
<div class="container mx-auto mt-8 grid grid-cols-12 gap-6">
<div class="col-span-3">
@livewire('category-navigation')
</div>
<div class="col-span-9">
{{ $slot }}
</div>
</div>
</main>
Here is how I define the Category component (app\Livewire\CategoryNavigation.php):
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Category;
class CategoryNavigation extends Component
{
public $categories;
public $currentCategory;
protected $listeners = ['category-selected' => 'setCategory'];
public function mount($selectedCategory = null)
{
$this->categories = Category::whereNull('parent_id')->where('status', 1)->get();
$this->currentCategory = $selectedCategory;
}
public function setCategory($slug)
{
$this->currentCategory = $slug;
}
public function navigateToCategory($fullPath)
{
return redirect($fullPath);
}
public function render()
{
return view('livewire.category-navigation', [
'categories' => $this->categories,
'currentCategory' => $this->currentCategory
]);
}
}
routes\web.php
<?php
use App\Livewire\ProductList;
use App\Livewire\ProductDetail;
use Illuminate\Support\Facades\Route;
Route::get('/product/{slug}', ProductDetail::class)->name('product.detail');
Route::get('/catalog/{slug}', ProductList::class)->where('slug', '.*')->name('products.byCategory');
app\Livewire\ProductList.php
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Category;
use App\Models\Product;
use Illuminate\Database\Eloquent\Collection;
class ProductList extends Component
{
public $category;
public $products = [];
protected $listeners = ['category-selected' => 'updateCategory'];
public function mount($slug = null)
{
// dd($slug);
if ($slug) {
$this->updateCategory($slug);
} else {
$this->category = Category::where('status', 1)->first();
$this->loadProducts();
}
}
public function updateCategory($slug)
{
$segments = explode('/', $slug);
$lastSlug = end($segments);
$this->category = Category::where('slug', $lastSlug)->first();
if ($this->category) {
$this->loadProducts();
}
}
private function loadProducts()
{
if (!$this->category) {
$this->products = [];
return;
}
$categoryIds = $this->getCategoryWithChildrenIds($this->category);
$this->products = Product::whereIn('category_id', $categoryIds)->get();
}
private function getCategoryWithChildrenIds($category)
{
$categoryIds = [$category->id];
foreach ($category->children as $child) {
$categoryIds = array_merge($categoryIds, $this->getCategoryWithChildrenIds($child));
}
return $categoryIds;
}
public function render()
{
return view('livewire.product-list', [
'categoryName' => $this->category ? $this->category->name : 'Select category',
'products' => $this->products
]);
}
}
app\Livewire\ProductDetail.php
<?php
namespace App\Livewire;
use Livewire\Component;
use App\Models\Product;
class ProductDetail extends Component
{
public $product;
public function mount($slug)
{
$this->product = Product::where('slug', $slug)->firstOrFail();
}
public function render()
{
return view('livewire.product-detail', [
'product' => $this->product
]);
}
}
resources\views\livewire\product-list.blade.php
<div class="container mx-auto mt-8">
<h1 class="text-2xl font-bold">
{{ $categoryName }}
</h1>
@if($products->isEmpty())
<p class="mt-4 text-gray-600">None Product</p>
@else
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mt-6">
@foreach ($products as $product)
<div class="border rounded-lg p-4 shadow-md">
<h2 class="text-lg font-semibold">
<a href="{{ route('product.detail', ['slug' => $product->slug]) }}" class="text-blue-500 hover:underline">
{{ $product->name }}
</a>
</h2>
<p class="text-gray-600">{{ $product->description }}</p>
</div>
@endforeach
</div>
@endif
</div>
resources\views\livewire\product-detail.blade.php
<div class="container mx-auto mt-8">
<h1 class="text-3xl font-bold">{{ $product->name }}</h1>
<div class="mt-4">
<p class="text-gray-700">{{ $product->description }}</p>
</div>
<div class="mt-6">
<a href="{{ url()->previous() }}" class="text-blue-500 hover:underline">← Back to list</a>
</div>
</div>
The main point is that the category list component should not refresh when a product list is loaded or when a product detail page is displayed.