Both approaches are valid, but each has its own trade-offs. Let’s break down the pros and cons of each, and then I’ll give you a recommendation.
1. Query in the render() method
Example:
public function render(): View
{
$query = Article::query();
if ($this->showOnlyPublished) {
$query->where('published', 1);
}
return view('livewire.article-list', [
'articles' => $query->paginate(10, pageName: 'articles-page'),
]);
}
Pros:
- Simple and straightforward.
- All logic is in one place.
- Easy to understand for small components.
Cons:
- If you have multiple places needing the same filtered articles, you’ll duplicate logic.
- Harder to test or reuse the filtering logic elsewhere.
- As your component grows,
render()can get cluttered.
2. Use a computed property (with optional helper methods)
Example:
public function render(): View
{
return view('livewire.article-list');
}
protected function applyFilter($query): Builder
{
return $this->showOnlyPublished
? $query->where('published', 1)
: $query;
}
#[Computed]
protected function articles(): LengthAwarePaginator
{
$query = Article::query();
$query = $this->applyFilter($query);
return $query->paginate(10, pageName: 'articles-page');
}
Pros:
- Separation of concerns:
render()just returns the view, and all data logic is in computed properties. - Filtering logic is reusable and testable (
applyFilter). - Cleaner and more maintainable as your component grows.
- If you need
articleselsewhere in the component, you can just use$this->articles.
Cons:
- Slightly more abstract, so it may take a bit more to understand at first glance.
- Requires Livewire 3+ for computed properties.
Recommendation
For most cases, especially as your component grows, the computed property approach is better. It keeps your code clean, modular, and easier to maintain. You can reuse the filtering logic, and your render() method stays simple.
So, prefer this:
public function render(): View
{
return view('livewire.article-list');
}
protected function applyFilter($query): Builder
{
return $this->showOnlyPublished
? $query->where('published', 1)
: $query;
}
#[Computed]
protected function articles(): LengthAwarePaginator
{
$query = Article::query();
$query = $this->applyFilter($query);
return $query->paginate(10, pageName: 'articles-page');
}
In your Blade view, you can then use:
@foreach($this->articles as $article)
<!-- display article -->
@endforeach
{{ $this->articles->links() }}
Summary:
- For small, simple components, either is fine.
- For maintainability and scalability, use computed properties and helper methods.
- Always aim for separation of concerns and reusable code.
Let me know if you have any follow-up questions!