# HookSlot (https://docs.salla.dev/twilight/react/hooks/hook-slot)



Use `HookSlot` when you want others (or you, later) to inject content at a spot without editing that component. It renders whatever was registered under its name with [`useHook`](https://docs.salla.dev/twilight/react/hooks/use-hook), and nothing when nothing was.

## Example [#example]

```tsx title="app/components/layout/Header.tsx"
import { HookSlot } from '@salla.sa/twilight-theme-engine/hooks/HookSlot';

export function Header() {
  return (
    <header>
      <HookSlot name="header:start" />
      <nav>{/* ... */}</nav>
      <HookSlot name="header:end" />
    </header>
  );
}
```

Add one rule to your global CSS so the element the slot renders for installed apps takes no space:

```css title="app/styles/app.css"
salla-hook { all: unset; display: none; }
```

## API [#api]

```ts
function HookSlot(props: HookSlotProps): JSX.Element | null;
```

| Prop        | Type                      | Description                                                                                                       |
| ----------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `name`      | `HookName \| string`      | Slot name: a `HookName` value or any string. Required.                                                            |
| `context?`  | `Record<string, unknown>` | Extra data passed to every handler.                                                                               |
| `fallback?` | `ReactNode`               | Rendered when no handler is registered for this name. Default: `null`.                                            |
| `ssr?`      | `boolean`                 | Also render the app element during server rendering. Default: `false`. The engine sets it for its `<head>` slots. |

A handler receives your `context` plus `twilight`: the full Twilight context (store, theme, currency and more).

## Slots the engine already renders [#slots-the-engine-already-renders]

The engine renders about 80 slots across the page frame, the storefront pages, the cart, the account area and the blog. [Slots overview](https://docs.salla.dev/twilight/react/slots) lists them all, with where each one sits on its page and the context it passes.

Each of them has a `HookName` member (86 in all), so `HookName.PRODUCT_START` and `'product:start'` name the same slot. A few members name slots no engine page renders: `BODY_INNER`, `HEAD_INNER`, the four `SEARCH_*` and the three `HOMEPAGE_*`. A handler there shows nothing until you render that `HookSlot` yourself.

## Gotchas [#gotchas]

* Handlers run in priority order, highest first, and their results render one after another.
* A handler that throws renders nothing. The error is logged in development only.
* Besides your handlers, the slot renders a `<salla-hook>` element where apps installed on the store inject their content. It is client-only by default to avoid a hydration mismatch.
* The slot re-renders when handlers are registered, removed or cleared for its name.
* It passes only your `context` and `twilight`. It does not read `ProductContextProvider` or `CartContextProvider`, so pass the product or cart yourself: `context={{ product }}`.

## Next [#next]

* [`useHook`](https://docs.salla.dev/twilight/react/hooks/use-hook) registers content in a slot from a component.
* [Add content to a slot](https://docs.salla.dev/twilight/react/recipes/add-content-to-a-slot) walks through it end to end.
* [Hooks and slots](https://docs.salla.dev/twilight/react/guide/hooks-and-slots) explains how slots and React hooks differ.
