前提・実現したいこと
Reactで複数動画を再生できるサイトを作成しています。
メインの動画とサブの動画で1ページに複数動画を表示しているのですが、サブ動画をクリックした際に入れ替えたいと考えております。
入れ替え自体は実現できているのですが、State更新時に動画が再読み込みされ、1からの再生となってしまいます。
再読み込みせず要素のみを入れ替える方法をご教授いただきたいです。
該当のソースコード
export const Video = () => { const { videoRelationId } = useParams(); // ローディングFLG(初回読み込み時) const [loading, setLoading] = useState(true); // video情報 [{}] const [video, setVideo] = useState(initialVideoState); // メインで表示しているVideo{} const [mainVideoId, setMainVideoId] = useState(); const [player, setPlayer] = useState([]); const [mainVideo, setMainVideo] = useState(<video></video>); const [isPlay, setIsPlay] = useState(false); // 現在のフレーム const [currentFrame, setCurrentFrame] = useState(0); // Video情報取得 useEffect(() => { getVideo(videoRelationId) .then(v => { setVideo(v); setMainVideoId(v[0].id); setLoading(false); }) .catch(e => { throw new Error(e); }) }, []); /** *Video描画 * @return {JSX} VideoPlayer */ const renderVideo = () => { // 2つ目以降はDivで囲うため、分割 const [first, ...rest] = video; const pointerEvent = (isCreatingTag) ? 'none' : 'auto'; const subVideoWrapStyle = { pointerEvents: pointerEvent } return ( <> {first && <VideoPlayer key={first.id} {...first} mainVideoFlg={true} player={player} setMainVideo={setMainVideo} setIsPlay={setIsPlay} createTagMouseDown={(isCreatingTag) ? createTagMouseDown : undefined} createTagMouseMove={(isMouseDown) ? createTagMouseMove : undefined} createTagMouseUp={(isMouseDown) ? createTagMouseUp : undefined} /> } <div className={classes.subVideoWrap} style={subVideoWrapStyle}> {rest.map(v => <VideoPlayer key={v.id} {...v} mainVideoFlg={false} player={player} all_video={video} setVideo={setVideo} mainVideo={mainVideo} setMainVideo={setMainVideo} setMainVideoId= {setMainVideoId} /> )} </div> </> ) }; return( <> { loading ? <div key='loading'> <p>loading...</p> </div> : <> <div className={classes.videoPlayer}> <div className={classes.videoContents}> {/* video表示 */} {renderVideo()} </div> </div> </> } </> ) }
React.js
1//子コンポーネント[Player.js] 2 3import React, { useRef, useEffect } from "react" 4 5export const VideoPlayer = React.memo(props => { 6 7 const ref = useRef(); 8 9 useEffect(() => { 10 props.player.push(ref.current); 11 }, []); 12 13 const src = 'http://localhost:8000' + props.video; 14 15 const style = (props.mainVideoFlg) ? { width: '100%' } : undefined; 16 17 /** 18 *ビデオ読み込み後Durationセット(MAINVIDEOのみ) 19 * 20 * @param {videoElement} 21 */ 22 const loadedMetadata = (target) => { 23 if(props.mainVideoFlg){ 24 props.setMainVideo(target); 25 } 26 } 27 28 /** 29 *動画終了時イベント 30 */ 31 const onEnded = () => { 32 if(props.mainVideoFlg){ 33 props.setIsPlay(false); 34 } 35 } 36 37 /** 38 *サブ動画クリックイベント(Swiching機能) 39 * @param {VideoElement} 40 */ 41 const changeVideo = (targetEle) => { 42 if(!props.mainVideoFlg){ 43 const newVideo = [...props.all_video]; 44 45 const target = newVideo.find(nv => String(nv.id) === targetEle.id); 46 newVideo.forEach((nv, index) => { 47 console.log(nv.id) 48 if(nv.id === target.id){ 49 newVideo[index] = newVideo.find(nv => String(nv.id) === props.mainVideo.id); 50 } 51 }); 52 newVideo[0] = target; 53 props.setVideo(newVideo); 54 props.setMainVideo(targetEle); 55 props.setMainVideoId(target.id); 56 } 57 } 58 59 return( 60 <> 61 <video muted 62 id={props.id} 63 style={style} 64 ref={ref} 65 onLoadedMetadata={() => loadedMetadata(ref.current)} 66 onEnded={() => onEnded()} 67 onClick={() => changeVideo(ref.current)} > 68 <source src={src} /> 69 </video> 70 </> 71 ) 72}); 73
###Constの情報
const [video, setVideo] = useState(initialVideoState);
[ { id: 'id', video: "https://hogehoge.com" }, { id: 'id', video: "https://mogemoge.com" } ]
・const [mainVideoId, setMainVideoId] = useState();
int 型でメインで表示しているVideoのIDを格納
・const [player, setPlayer] = useState([]);
Videoタグを配列形式で格納(playやposeなどvideoを扱うため)
[ <video></video>, <video></video> ]
・const [mainVideo, setMainVideo] = useState(<video></video>);
メインのVideoタグを格納
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。