refactor(packages): move store attach lifecycle to provider (#975)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
rahim
2026-03-17 15:50:39 -07:00
committed by GitHub
co-authored by Claude Opus 4.6
parent 7bacb1b2ae
commit d535282f03
26 changed files with 378 additions and 265 deletions
@@ -0,0 +1,33 @@
---
title: useMediaAttach
description: Hook to register a custom media element with the player context
---
import UtilReference from "@/components/docs/api-reference/UtilReference.astro";
`useMediaAttach` returns a setter function for attaching a media element to the player context. The built-in `<Video>` and `<Audio>` components use this internally -- you only need it when building a custom media element.
```tsx title="CustomMedia.tsx"
import { useMediaAttach } from "@videojs/react";
function CustomMedia({ src }: { src: string }) {
const setMedia = useMediaAttach();
return <video ref={setMedia} src={src} />;
}
```
## Who needs this
You only need `useMediaAttach` if you're replacing the built-in `<Video>` or `<Audio>` components with a custom element. For example, if you're...
- Wrapping a third-party video player
- Using a `<canvas>` or WebGL-based renderer
- Building a custom `<audio>` element with additional markup
For standard `<video>` and `<audio>` playback, use the built-in components.
## Safe outside Provider
Returns `undefined` when called outside a Player `Provider`. Check the return value before using it -- this avoids crashes in components that may render outside the player tree.
<UtilReference util="useMediaAttach" />
@@ -1,47 +0,0 @@
---
title: useMediaRegistration
description: Hook to register a custom media element with the player context
---
import UtilReference from "@/components/docs/api-reference/UtilReference.astro";
`useMediaRegistration` returns a setter function for registering a media element with the player context. The built-in `<Video>` and `<Audio>` components use this internally -- you only need it when building a custom media element.
```tsx title="CustomMedia.tsx"
import { useMediaRegistration } from "@videojs/react";
import { useRef, useEffect } from "react";
function CustomMedia({ src }: { src: string }) {
const setMedia = useMediaRegistration();
const ref = useRef<HTMLVideoElement>(null);
useEffect(() => {
if (ref.current && setMedia) {
setMedia(ref.current);
return () => setMedia(null);
}
}, [setMedia]);
return <video ref={ref} src={src} />;
}
```
## Who needs this
You only need `useMediaRegistration` if you're replacing the built-in `<Video>` or `<Audio>` components with a custom element. For example, if you're...
- Wrapping a third-party video player
- Using a `<canvas>` or WebGL-based renderer
- Building a custom `<audio>` element with additional markup
For standard `<video>` and `<audio>` playback, use the built-in components.
## Cleanup pattern
Always return a cleanup function that passes `null` to the setter. This detaches the media element when the component unmounts, preventing stale references in the store.
## Safe outside Provider
Returns `undefined` when called outside a Player `Provider`. Check the return value before using it -- this avoids crashes in components that may render outside the player tree.
<UtilReference util="useMediaRegistration" />
@@ -12,7 +12,7 @@ import BasicUsageDemoReact from "@/components/docs/demos/use-media/react/css/Bas
import basicUsageReactTsx from "@/components/docs/demos/use-media/react/css/BasicUsage.tsx?raw";
import basicUsageReactCss from "@/components/docs/demos/use-media/react/css/BasicUsage.css?raw";
`Player.useMedia` returns the current `HTMLMediaElement` (or `null` if no media element has been registered yet). Use it to interact directly with the native media element when needed. It must be called within a `Player.Provider`. The media element becomes available after a `<Video>` or `<Audio>` component mounts inside the provider tree. Also available as a standalone import (`import { useMedia } from '@videojs/react'`) — identical behavior, no typing difference. To register a custom media element instead of the built-in components, see <DocsLink slug="reference/use-media-registration">`useMediaRegistration`</DocsLink>.
`Player.useMedia` returns the current `HTMLMediaElement` (or `null` if no media element has been registered yet). Use it to interact directly with the native media element when needed. It must be called within a `Player.Provider`. The media element becomes available after a `<Video>` or `<Audio>` component mounts inside the provider tree. Also available as a standalone import (`import { useMedia } from '@videojs/react'`) — identical behavior, no typing difference. To attach a custom media element instead of the built-in components, see <DocsLink slug="reference/use-media-attach">`useMediaAttach`</DocsLink>.
## Examples
@@ -40,7 +40,7 @@ For most use cases, use the focused hooks instead:
| -------------------------- | ----------------------------------------------------------------------------------- |
| Store access with selector | <DocsLink slug="reference/use-player">`usePlayer`</DocsLink> |
| Current media element | <DocsLink slug="reference/use-media">`useMedia`</DocsLink> |
| Register custom media | <DocsLink slug="reference/use-media-registration">`useMediaRegistration`</DocsLink> |
| Attach custom media | <DocsLink slug="reference/use-media-attach">`useMediaAttach`</DocsLink> |
These hooks read from the same context internally. `usePlayerContext` exposes the raw context value -- use it when you need multiple context fields in one call or when building a custom abstraction over the player context.