Component Hooks
Livewire Concept
A Component Hook is a class that subscribes to events in the Magewire request pipeline. Hooks drive every built-in Feature, including notifications, redirects, rate limiting, and backwards compatibility. They are also the intended extension point for custom framework-level behaviour.
Unlike lifecycle hooks on a component class (which only see their own component), a Component Hook sees every component in the pipeline.
Anatomy
Extend Magewirephp\Magewire\ComponentHook and implement provide(). Inside provide(), register listeners with Magewirephp\Magewire\on(…).
<?php
namespace Vendor\Module\Magewire\Hooks;
use Magewirephp\Magewire\Component;
use Magewirephp\Magewire\ComponentHook;
use Magento\Framework\View\Element\AbstractBlock;
use function Magewirephp\Magewire\on;
class SupportLogRender extends ComponentHook
{
public function __construct(
private \Psr\Log\LoggerInterface $logger
) {}
public function provide(): void
{
on('render', function (Component $component, AbstractBlock $block) {
$started = microtime(true);
return function (string $html) use ($component, $started): string {
$this->logger->debug(sprintf(
'Magewire: %s rendered in %.1fms',
$component::class,
(microtime(true) - $started) * 1000,
));
return $html;
};
});
}
}
Initial and later phases
on('event', $callback) is a middleware. The behaviour depends on what $callback returns:
| Return value | Runs as |
|---|---|
null / nothing |
Before-only listener |
Closure |
Initial + later phase. The closure receives the values supplied when the triggering code invokes the returned dispatcher. |
on('render', function (Component $component, AbstractBlock $block, array $properties): \Closure {
// Initial phase: inspect the block and public properties before final HTML is processed.
return function (string $html): string {
// Later phase: transform the rendered HTML.
return $html;
};
});
Registering a hook
Register the hook class on the Magewirephp\Magewire\Features collection in area-scoped DI. A global addition to this
array can be replaced when Magento loads the later area configuration:
<type name="Magewirephp\Magewire\Features">
<arguments>
<argument name="items" xsi:type="array">
<item name="support_log_render" xsi:type="array">
<item name="type" xsi:type="string">
Vendor\Module\Magewire\Hooks\SupportLogRender
</item>
<item name="sort_order" xsi:type="number">10000</item>
<item name="boot_mode" xsi:type="number">30</item>
</item>
</argument>
</arguments>
</type>
To boot after a specific core feature, add a sequence (see Ordering items). A hook
with boot_mode 30, like the one above, cannot sequence after a LAZY feature; drop the boot_mode or align it
first.
The Features collection calls provide() on the hook when it registers, giving it a chance to subscribe to events.
Register in adminhtml/di.xml too if the hook is needed in the admin area. Do not put a ComponentHook in the
Mechanisms collection: Mechanisms use a different boot contract and do not register the hook with
ComponentHookRegistry.
Events
Adding hook events
Prefer subscribing to existing hook events when extending Magewire. Additional events are fine for custom project or extension code, where they can serve that code's specific needs. In Magewire core, adding events beyond Livewire's default hooks is an exception.
A new core hook must represent a meaningful framework event and be useful beyond the single integration that prompted it. Before proposing one, explain why existing hooks cannot cover the behaviour and describe more than one use case. The event name must accurately describe what happens where it is emitted, with clear timing and scope for listeners.
Every additional hook becomes part of the framework's extension contract. Adding hooks wherever another feature needs a callback leads to an uncontrolled collection of narrowly useful events, with names that may promise more than their individual call sites provide.
For example, a proposed magewire:component:reset hook needs a clear definition of what is reset and when the event
fires. Adding it solely to make one feature work elsewhere is insufficient justification; the reset event itself must
make sense as a reusable extension point.
Any new Magewire-specific core hook must use the magewire: prefix. Existing Livewire hook names remain unchanged.
The prefix identifies the hook's origin; it does not replace the need for a well-defined, broadly useful event.
Lifecycle
| Event | Fires |
|---|---|
magewire:component:construct |
Component instantiated during initial page load |
magewire:component:reconstruct |
Component instantiated during an update roundtrip |
magewire:component:build |
Component has been fully built, after component modifiers ran and the resolver assembled it |
pre-mount |
Before mount() runs |
mount.stub |
Placeholder mount step |
mount |
mount() completes |
hydrate |
Component hydrated from snapshot |
update |
Property update applied |
call |
Public method invoked |
render |
Template about to render |
render.placeholder |
Placeholder render step |
dehydrate |
Snapshot being written |
destroy |
Component finalising |
Signatures vary per event and evolve between releases. Inspect the emit site in core (grep for trigger('event-name') for the exact arguments.
Request / response
| Event | Fires |
|---|---|
request |
Update controller received a request |
response |
Response is about to be sent |
exception |
Uncaught exception escaped the component |
flush-state |
State is being flushed |
profile |
Profiling event |
Checksum
| Event | Fires |
|---|---|
checksum.generate |
Generating an outgoing snapshot HMAC |
checksum.verify |
Verifying an incoming snapshot HMAC |
checksum.fail |
Verification failed |
snapshot-verified |
Verification succeeded |
Morph
Emitted on the JS side and available via Magewire.hook(…):
morph.updating, morph.removed, element.init, component.init, commit.
Magento Observer bridge
For listeners that prefer Magento's observer system, Magewire re-emits an explicit lifecycle map with the prefix magewire_on_. Non-alphanumeric characters become underscores (magewire:component:construct → magewire_on_magewire_component_construct).
<event name="magewire_on_render">
<observer name="MagewireOnRender"
instance="Vendor\Module\Observer\Frontend\MagewireOnRender" />
</event>
class MagewireOnRender implements \Magento\Framework\Event\ObserverInterface
{
public function execute(\Magento\Framework\Event\Observer $observer): void
{
/** @var \Magewirephp\Magewire\Features\SupportMagentoObserverEvents\DTO\ListenerDataTransferObject $listener */
$listener = $observer->getData('listener');
$listener->with(function (Component $component, AbstractBlock $block) {
return function (string $html): string {
return $html;
};
});
}
}
Prefer Component Hooks for most work because they are faster (no observer dispatch), typed, and area-scoped.
Component Hook vs. Feature
A Feature is a Component Hook with a name and a layout footprint. It typically owns PHTML, CSS, or JS assets rendered into magewire.features and friends. A Component Hook is the smaller primitive. Every Feature contains at least one hook class; a hook class without layout assets does not need Feature packaging.
See Features.
Related
- Mechanisms
- Features
- Lifecycle Hooks: per-component lifecycle.