Player - Best practices
Avoid re-renders of the <Player>
The following pattern is not ideal because every time the time updates, the <Player> is being re-rendered:
❌ Problematictsxexport constApp :React .FC = () => {constplayerRef =useRef <PlayerRef >(null);const [currentTime ,setCurrentTime ] =useState (0);useEffect (() => {playerRef .current ?.addEventListener ("timeupdate", (e ) => {setCurrentTime (e .detail .frame );});}, []);return (<div ><Player ref ={playerRef }component ={MyVideo } {...otherProps } /><div >Current time: {currentTime }</div ></div >);};
❌ Problematictsxexport constApp :React .FC = () => {constplayerRef =useRef <PlayerRef >(null);const [currentTime ,setCurrentTime ] =useState (0);useEffect (() => {playerRef .current ?.addEventListener ("timeupdate", (e ) => {setCurrentTime (e .detail .frame );});}, []);return (<div ><Player ref ={playerRef }component ={MyVideo } {...otherProps } /><div >Current time: {currentTime }</div ></div >);};
We advise to render your controls and UI as a sibling to the component that renders the <Player> and pass a ref to the player as a prop:
✅ BettertsxconstPlayerOnly :React .FC <{playerRef :React .RefObject <PlayerRef >;}> = ({playerRef }) => {return <Player ref ={playerRef }component ={MyVideo } {...otherProps } />;};constControlsOnly :React .FC <{playerRef :React .RefObject <PlayerRef >;}> = ({playerRef }) => {const [currentTime ,setCurrentTime ] =useState (0);useEffect (() => {playerRef .current ?.addEventListener ("timeupdate", (e ) => {setCurrentTime (e .detail .frame );});}, []);return <div >Current time: {currentTime }</div >;};export constApp :React .FC = () => {constplayerRef =useRef <PlayerRef >(null);return (<><PlayerOnly playerRef ={playerRef } /><ControlsOnly playerRef ={playerRef } /></>);};
✅ BettertsxconstPlayerOnly :React .FC <{playerRef :React .RefObject <PlayerRef >;}> = ({playerRef }) => {return <Player ref ={playerRef }component ={MyVideo } {...otherProps } />;};constControlsOnly :React .FC <{playerRef :React .RefObject <PlayerRef >;}> = ({playerRef }) => {const [currentTime ,setCurrentTime ] =useState (0);useEffect (() => {playerRef .current ?.addEventListener ("timeupdate", (e ) => {setCurrentTime (e .detail .frame );});}, []);return <div >Current time: {currentTime }</div >;};export constApp :React .FC = () => {constplayerRef =useRef <PlayerRef >(null);return (<><PlayerOnly playerRef ={playerRef } /><ControlsOnly playerRef ={playerRef } /></>);};
This is much more performant because the <Player> gets rerendered less often.
This advice is mainly for frequently updated state like the current time. Keeping state like a loop toggle in the parent component is fine, because it is not expected to change frequently.
A more complex example can be found here.
Pass the user interaction event to play()
When you listen to an onClick() event, the browser will give you an event argument.
Pass it on to .play() and .toggle() to have the lowest chance of hitting autoplay restrictions that the browser may impose.