The #[Reactive] attribute makes a child component's property automatically update when the parent changes the value being passed in.
Apply the #[Reactive] attribute to any property that should react to parent changes:
<?php // resources/views/components/⚡todo-count.blade.php
use Livewire\Attributes\Reactive;
use Livewire\Attributes\Computed;
use Livewire\Component;
new class extends Component {
#[Reactive] // [tl! highlight]
public $todos;
#[Computed]
public function count()
{
return $this->todos->count();
}
};
?>
<div>
Count: {{ $this->count }}
</div>Now when the parent component adds or removes todos, the child component will automatically update to reflect the new count.
By default, Livewire props are not reactive. When a parent component updates, only the parent's state is sent to the server—not the child's. This minimizes data transfer and improves performance.
Here's what happens without #[Reactive]:
<?php // resources/views/components/⚡todos.blade.php
use Livewire\Component;
new class extends Component {
public $todos = [];
public function addTodo($text)
{
$this->todos[] = ['text' => $text];
// Child components with $todos props won't automatically update
}
};
?>
<div>
<livewire:todo-count :$todos />
<button wire:click="addTodo('New task')">Add Todo</button>
</div>Without #[Reactive] on the child's $todos property, adding a todo in the parent won't update the child's count.
When you add #[Reactive]:
$todos property$todos value to the child during the responseThis creates a "reactive" relationship similar to frontend frameworks like Vue or React.
[!warning] Use reactive properties sparingly Reactive properties require additional data to be sent between server and client on every parent update. Only use #[Reactive] when necessary for your use case.When to use:
When NOT to use:
Here's a practical example of a search component with reactive results:
<?php // resources/views/components/⚡search.blade.php
use Livewire\Component;
use App\Models\Post;
new class extends Component {
public $query = '';
public function posts()
{
return Post::where('title', 'like', "%{$this->query}%")->get();
}
};
?>
<div>
<input type="text" wire:model.live="query" placeholder="Search posts...">
<livewire:search-results :posts="$this->posts()" /> <!-- [tl! highlight] -->
</div><?php // resources/views/components/⚡search-results.blade.php
use Livewire\Attributes\Reactive;
use Livewire\Component;
new class extends Component {
#[Reactive] // [tl! highlight]
public $posts;
};
?>
<div>
@foreach($posts as $post)
<div wire:key="{{ $post->id }}">{{ $post->title }}</div>
@endforeach
</div>As the user types, the parent's $posts changes and the child's results automatically update.
For loosely coupled components, consider using events instead of reactive props:
// Parent dispatches event
$this->dispatch('todos-updated', todos: $this->todos);
// Child listens for event
#[On('todos-updated')]
public function handleTodosUpdate($todos)
{
$this->todos = $todos;
}Events provide more flexibility but require explicit communication between components.
For more information about parent-child communication and component architecture, see the Nesting Components documentation.