plyr-react v6 modernizes the API, tightens TypeScript typings, and simplifies lifecycle behavior—expect a small set of breaking changes but a much clearer migration path and better DX.
Design goals and why they matter
v6 was driven by three practical goals: clarity, type safety, and predictability. The public surface was intentionally narrowed so consumers only rely on well-documented, stable exports. TypeScript-first typings reduce runtime surprises and make editor tooling actually helpful. Lifecycle and concurrency fixes address real-world flakiness when players mount/unmount rapidly in React apps. These changes make the library easier to maintain and safer to use in production, especially in large codebases and CI pipelines.
Key design decisions (technical summary)
- Named public API: The component and hook are explicit exports. This reduces accidental reliance on internal utilities and enables better tree-shaking.
-
Hook-first ergonomics:
usePlyris the recommended path for imperative control; the component remains for simple declarative use. The hook returns a typedinstanceand stable attach/detach helpers. -
Stronger typings: Events are modeled as discriminated unions and the player instance exposes typed methods (
play,pause,seek,on,off). This eliminates manyanycasts and improves DX. - Lifecycle hardening: Initialization waits for the DOM node, defers non-critical setup, and guards against concurrent inits; cleanup is idempotent to avoid double-destroy errors.
- Distribution clarity: ESM and CJS entry points are preserved, and CSS is consolidated to a single canonical import path to avoid bundler surprises.
Real-world migration examples
Below are concise, practical changes you’ll make when upgrading from v5 → v6.
1) Update package and imports
npm install plyr-react@^6.0.0
// v5
import Plyr from 'plyr-react';
import 'plyr-react/plyr.css';
// v6
import { Plyr, usePlyr } from 'plyr-react';
import 'plyr-react/dist/plyr.css';
Important: v6 uses named exports and a consolidated CSS path—update imports accordingly.
2) Flattened props and typed callbacks
// v5 style
<Plyr
source={{ type: 'video', sources: [{ src: '/video.mp4' }] }}
options={{ controls: ['play', 'progress'] }}
onReady={(player) => { /* untyped */ }}
/>
// v6 style
<Plyr
source={{ type: 'video', sources: [{ src: '/video.mp4' }] }}
controls={['play', 'progress']}
onReady={(instance: PlyrInstance) => { /* typed instance */ }}
/>
Important: Some props were flattened or renamed; check the changelog for exact mappings.
3) Using usePlyr for advanced control
import { useRef, useEffect } from 'react';
import { usePlyr } from 'plyr-react';
function Advanced() {
const ref = useRef(null);
const { instance, attach } = usePlyr();
useEffect(() => { if (ref.current) attach(ref.current); }, [attach]);
useEffect(() => {
if (!instance) return;
instance.on('timeupdate', (e) => { /* typed payload */ });
return () => instance.off('timeupdate');
}, [instance]);
return <div ref={ref} />;
}
Important: usePlyr gives explicit attach/detach control and a typed instance—prefer it for complex integrations.
Testing and rollout tips
-
Run
tsc --noEmitto catch typing regressions. - Smoke test play/pause/seek/fullscreen in a headless browser.
- Search for internal imports in your codebase and replace them with public types and APIs.
v6 trades a few breaking changes for long-term stability, better DX, and fewer runtime surprises.
Top comments (0)