Components
Livewire components are essentially PHP classes with properties and methods that can be called directly from a Blade template. This powerful combination allows you to create full-stack interactive interfaces with a fraction of the effort and complexity of modern JavaScript alternatives.
This guide covers everything you need to know about creating, rendering, and organizing Livewire components. You'll learn about the different component formats available (single-file, multi-file, and class-based), how to pass data between components, and how to use components as full pages.
Creating components
You can create a component using the make:livewire Artisan command:
php artisan make:livewire post.create
This creates a single-file component at:
resources/views/components/post/⚡create.blade.php
<?php use Livewire\Component; new class extends Component { public $title = ''; public function save() { // Save logic here... }};?> <div> <input wire:model="title" type="text"> <button wire:click="save">Save Post</button></div>
You might be wondering about the lightning bolt in the filename. This small touch serves a practical purpose: it makes Livewire components instantly recognizable in your editor's file tree and search results. Since it's a Unicode character, it works seamlessly across all platforms — Windows, macOS, Linux, Git, and your production servers.
The emoji is completely optional and if you find it outside your comfort zone you can disable it entirely in your config/livewire.php file:
'make_command' => [ 'emoji' => false,],
Creating page components
When creating components that will be used as full pages, use the pages:: namespace to organize them in a dedicated directory:
php artisan make:livewire pages::post.create
This creates the component at resources/views/pages/post/⚡create.blade.php. This organization makes it clear which components are pages versus reusable UI components.
Learn more about using components as pages in the Page components section below. You can also register your own custom namespaces—see the Component namespaces documentation.
Multi-file components
As your component or project grows, you might find the single-file approach limiting. Livewire offers a multi-file alternative that splits your component into separate files for better organization and IDE support.
To create a multi-file component, pass the --mfc flag:
php artisan make:livewire post.create --mfc
This creates a directory with all related files together:
resources/views/components/post/⚡create/├── create.php # PHP class├── create.blade.php # Blade template├── create.js # JavaScript (optional, with --js flag)└── create.test.php # Pest test (optional, with --test flag)
Converting between formats
Livewire provides the livewire:convert command to seamlessly convert components between single-file and multi-file formats.
Auto-detect and convert:
php artisan livewire:convert post.create# Single-file → Multi-file (or vice versa)
Explicitly convert to multi-file:
php artisan livewire:convert post.create --mfc
This will parse your single-file component, create a directory structure, split the files, and delete the original.
Explicitly convert to single-file:
php artisan livewire:convert post.create --sfc
This combines all files back into a single file and deletes the directory.
If your multi-file component has a test file, you'll be prompted to confirm before conversion since test files cannot be preserved in the single-file format.
When to use each format
Single-file components (default):
- Best for most components
- Keeps related code together
- Easy to understand at a glance
- Perfect for small to medium components
Multi-file components:
- Better for large, complex components
- Improved IDE support and navigation
- Clearer separation when components have significant JavaScript
Class-based components:
- Familiar to developers from Livewire v2/v3
- Traditional Laravel separation of concerns
- Better for teams with established conventions
- See Class-based components below
Rendering components
You can include a Livewire component within any Blade template using the <livewire:component-name /> syntax:
<livewire:component-name />
If the component is located in a sub-directory, you can indicate this using the dot (.) character:
resources/views/components/post/⚡create.blade.php
<livewire:post.create />
For namespaced components—like pages::—use the namespace prefix:
<livewire:pages::post.create />
Passing props
To pass data into a Livewire component, you can use prop attributes on the component tag:
<livewire:post.create title="Initial Title" />
For dynamic values or variables, prefix the attribute with a colon:
<livewire:post.create :title="$initialTitle" />
Data passed into components is received through the mount() method:
<?php use Livewire\Component; new class extends Component { public $title; public function mount($title = null) { $this->title = $title; } // ...};
You can think of the mount() method as a class constructor. It runs when the component initializes, but not on subsequent requests within a page's session. You can learn more about mount() and other helpful lifecycle hooks within the lifecycle documentation.
To reduce boilerplate code, you can omit the mount() method and Livewire will automatically set any properties with names matching the passed values:
<?php use Livewire\Component; new class extends Component { public $title; // Automatically set from prop // ...};
The $title property will not update automatically if the outer :title="$initialValue" changes after the initial page load. This is a common point of confusion when using Livewire, especially for developers who have used JavaScript frameworks like Vue or React and assume these parameters behave like "reactive props" in those frameworks. But, don't worry, Livewire allows you to opt-in to making your props reactive.
Passing route parameters as props
When using components as pages, you can pass route parameters directly to your component. The route parameters are automatically passed to the mount() method:
Route::livewire('/posts/{id}', 'pages::post.show');
<?php // resources/views/pages/post/⚡show.blade.php use Livewire\Component; new class extends Component { public $postId; public function mount($id) { $this->postId = $id; }};
Livewire also supports Laravel's route model binding:
Route::livewire('/posts/{post}', 'pages::post.show');
<?php // resources/views/pages/post/⚡show.blade.php use App\Models\Post;use Livewire\Component; new class extends Component { public Post $post; // Automatically bound from route // No mount() needed - Livewire handles it automatically};
Page components
Components can be routed to directly as full pages using Route::livewire(). This is one of Livewire's most powerful features, allowing you to build entire pages without traditional controllers.
Route::livewire('/posts/create', 'pages::post.create');
When a user visits /posts/create, Livewire will render the pages::post.create component inside your application's layout file.
Page components work just like regular components, but they're rendered as full pages with access to:
- Custom layouts
- Page titles
- Route parameters and model binding
- Named slots for layouts
For complete information about page components, including layouts, titles, and advanced routing, see the Pages documentation.
Accessing data in views
Livewire provides several ways to pass data to your component's Blade view. Each approach has different performance and security characteristics.
Component properties
The simplest approach is using public properties, which are automatically available in your Blade template:
<?php use Livewire\Component; new class extends Component { public $title = 'My Post';};
<div> <h1>{{ $title }}</h1></div>
Protected properties must be accessed with $this->:
public $title = 'My Post'; // Available as {{ $title }}protected $apiKey = 'secret-key'; // Available as {{ $this->apiKey }}
Unlike public properties, protected properties are never sent to the frontend and cannot be manipulated by users. This makes them safe for sensitive data. However, they are not persisted between requests, which limits their usefulness in most Livewire scenarios. They're best used for static values defined in the property declaration that you don't want exposed client-side.
For complete information about properties, including persistence behavior and advanced features, see the properties documentation.
Computed properties
Computed properties are methods that act like memoized properties. They're perfect for expensive operations like database queries:
use Livewire\Attributes\Computed; #[Computed]public function posts(){ return Post::with('author')->latest()->get();}
<div> @foreach ($this->posts as $post) <article wire:key="{{ $post->id }}">{{ $post->title }}</article> @endforeach</div>
Notice the $this-> prefix - this tells Livewire to call the method and cache the result for the current request only (not between requests). For more details, see the computed properties section in the properties documentation.
Passing data from render()
Similar to a controller, you can pass data directly to the view using the render() method:
public function render(){ return $this->view([ 'author' => Auth::user(), 'currentTime' => now(), ]);}
Keep in mind that render() runs on every component update, so avoid expensive operations here unless you need fresh data on every update.
Organizing components
While Livewire automatically discovers components in the default resources/views/components/ directory, you can customize where Livewire looks for components and organize them using namespaces.
Component namespaces
Component namespaces allow you to organize components into dedicated directories with a clean reference syntax.
By default, Livewire provides two namespaces:
pages::— Points toresources/views/pages/layouts::— Points toresources/views/layouts/
You can define additional namespaces in your config/livewire.php file:
'component_namespaces' => [ 'layouts' => resource_path('views/layouts'), 'pages' => resource_path('views/pages'), 'admin' => resource_path('views/admin'), // Custom namespace 'widgets' => resource_path('views/widgets'), // Another custom namespace],
Then use them when creating, rendering, and routing:
php artisan make:livewire admin::users-table
<livewire:admin::users-table />
Route::livewire('/admin/users', 'admin::users-table');
Additional component locations
If you want Livewire to discover components in additional directories beyond the defaults, you can configure them in your config/livewire.php file:
'component_paths' => [ resource_path('views/components'), resource_path('views/admin/components'), resource_path('views/widgets'),],
Now Livewire will automatically discover components in all these directories.
Programmatic registration
For more dynamic scenarios (like package development or runtime configuration), you can register components, locations, and namespaces programmatically in a service provider:
Register an individual component:
use Livewire\Livewire; // In a service provider's boot() method (e.g., App\Providers\AppServiceProvider)Livewire::addComponent( name: 'custom-button', viewPath: resource_path('views/ui/button.blade.php'));
Register a component directory:
Livewire::addLocation( viewPath: resource_path('views/admin/components'));
Register a namespace:
Livewire::addNamespace( namespace: 'ui', viewPath: resource_path('views/ui'));
This approach is useful when you need to register components conditionally or when building Laravel packages that provide Livewire components.
Registering class-based components
For class-based components, use the same methods but with the class parameter instead of path:
use Livewire\Livewire; // In a service provider's boot() method (e.g., App\Providers\AppServiceProvider) // Register an individual class-based componentLivewire::addComponent( name: 'todos', \App\Livewire\Todos::class); // Register a location for class-based componentsLivewire::addLocation( classNamespace: 'App\\Admin\\Livewire'); // Create a namespace for class-based componentsLivewire::addNamespace( namespace: 'admin', classNamespace: 'App\\Admin\\Livewire', classPath: app_path('Admin/Livewire'), classViewPath: resource_path('views/admin/livewire'));
Class-based components
For teams migrating from Livewire v3 or those who prefer a more traditional Laravel structure, Livewire fully supports class-based components. This approach separates the PHP class and Blade view into different files in their conventional locations.
Creating class-based components
php artisan make:livewire CreatePost --class
This creates two separate files:
app/Livewire/CreatePost.php
<?php namespace App\Livewire; use Livewire\Component; class CreatePost extends Component{ public function render() { return view('livewire.create-post'); }}
resources/views/livewire/create-post.blade.php
<div> {{-- ... --}}</div>
When to use class-based components
Use class-based components when:
- Migrating from Livewire v2/v3
- Your team prefers a more traditional file structure
- You have established conventions around class-based architecture
Use single-file or multi-file components when:
- Starting a new Livewire v4 project
- You want better component colocation
- You want to use the latest Livewire conventions
Configuring default component type
If you want class-based components by default, configure it in config/livewire.php:
'make_command' => [ 'type' => 'class',],
Customizing component stubs
You can customize the files (or stubs) Livewire uses to generate new components by running:
php artisan livewire:stubs
This creates stub files in your application that you can modify:
Single-file component stubs:
stubs/livewire-sfc.stub— Single-file components
Multi-file component stubs:
stubs/livewire-mfc-class.stub— PHP class for multi-file componentsstubs/livewire-mfc-view.stub— Blade view for multi-file componentsstubs/livewire-mfc-js.stub— JavaScript for multi-file componentsstubs/livewire-mfc-test.stub— Pest test for multi-file components
Class-based component stubs:
stubs/livewire.stub— PHP class for class-based componentsstubs/livewire.view.stub— Blade view for class-based components
Additional stubs:
stubs/livewire.attribute.stub— Attribute classesstubs/livewire.form.stub— Form classes
Once published, Livewire will automatically use your custom stubs when generating new components.
Troubleshooting
Component not found
Symptom: Error message like "Component [post.create] not found" or "Unable to find component"
Solutions:
- Verify the component file exists at the expected path
- Check that the component name in your view matches the file structure (dots for subdirectories)
- For namespaced components, ensure the namespace is defined in
config/livewire.phpor manually registered in a service provider - Try clearing your view cache:
php artisan view:clear
Component shows blank or doesn't render
Common causes:
- Missing root element in your Blade template (Livewire requires exactly one root element)
- Syntax errors in the PHP section of your component
- Check your Laravel logs for detailed error messages
Class name conflicts
Symptom: Errors about duplicate class names when using single-file components
Solution: This can happen if you have multiple single-file components with the same name in different directories. Either:
- Rename one of the components to be unique
- Namespace one of the directories for more clear separation
See also
- Properties — Manage component state and data
- Actions — Handle user interactions with methods
- Pages — Use components as full pages with routing
- Nesting — Compose components together and pass data between them
- Lifecycle Hooks — Execute code at specific points in a component's lifecycle