Player - 最佳实践
避免 <Player>
的重新渲染
以下模式并不理想,因为每次时间更新时,<Player>
都会被重新渲染:
❌ 有问题tsx
export 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 >);};
❌ 有问题tsx
export 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 >);};
我们建议将您的控件和用户界面作为 <Player>
渲染的兄弟元素,并将一个 ref 作为 prop 传递给播放器:
✅ 更好tsx
constPlayerOnly :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 } /></>);};
✅ 更好tsx
constPlayerOnly :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 } /></>);};
这样做更高效,因为 <Player>
的重新渲染次数更少。
这个建议主要针对像当前时间这样频繁更新的状态。在父组件中保留像 loop
切换这样的状态是可以的,因为不会经常更改。
将用户交互事件传递给 play()
当您监听 onClick()
事件时,浏览器会给您一个 event
参数。
将其传递给 .play()
和 .toggle()
可以最大程度地减少浏览器可能施加的自动播放限制。
对 inputProps
进行记忆化处理
不对 inputProps
进行记忆化处理会导致整个树重新渲染太多次,从而创建瓶颈。
Player.tsxtsx
import {Player } from "@remotion/player";import {useState ,useMemo } from "react";import {MyVideo } from "./remotion/MyVideo";export constApp :React .FC = () => {const [text ,setText ] =useState ("world");constinputProps =useMemo (() => {return {text ,};}, [text ]);return (<Player component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}inputProps ={inputProps }/>);};
Player.tsxtsx
import {Player } from "@remotion/player";import {useState ,useMemo } from "react";import {MyVideo } from "./remotion/MyVideo";export constApp :React .FC = () => {const [text ,setText ] =useState ("world");constinputProps =useMemo (() => {return {text ,};}, [text ]);return (<Player component ={MyVideo }durationInFrames ={120}compositionWidth ={1920}compositionHeight ={1080}fps ={30}inputProps ={inputProps }/>);};