追記
質問をしてから、気付きました。
iframeが表示されないのは、stateで管理されていないからかもしれません。
iframeにstateして、再描画できるようにしてみます。
→ うまくいかない。
どうやら、
前の <Vimeo /> をアンマウントする前に、次の <Vimeo /> がマウントされているのが原因?
前提・実現したいこと
実現したいこと
ページネーションでのページ切り替え時に、
vimeoのiframeの中身が切り替わらないため、
切り替えて表示させたいです。
前提
- react
- ページネーションは、@material-uiを使用。
- firebase realtime database
表示しているリストのデータについて
- リストを全件取得
- リストを分割してページごとに出し分け
発生している問題・エラーメッセージ
- 画面上でだけ、iframeの中身が変更されない。
- videoIdの変更は、コンポーネントに渡って来ている。
該当のソースコード
vimeoを表示している部分
js
1// Vimeo.js 2import React, { useEffect, useState } from 'react' 3import Player from "@vimeo/player" 4import { itemRef } from '../../firebase' 5 6export const Vimeo = (props) => { 7 const { videoId, item } = props 8 const uploadState = !!item.videoUploaded 9 const [uploaded, setUploaded] = useState(uploadState) 10 11 const iframeId = `vimeo-${videoId}` 12 13 // vimeoのアップロードが完了したか確認 14 // アプロード完了フラグは、DBで管理 15 const check = (player) => { 16 if (!uploaded) { 17 player.getVideoUrl().then((url) => { 18 console.log('動画のURL;', url); 19 setUploaded(true) 20 itemRef.child(item.key).update({videoUploaded: true}) 21 }).catch((error) => { 22 console.log('error', error, videoId); 23 }) 24 } 25 } 26 27 // マウント時・uploaded変更時に実行 28 useEffect(() => { 29 const options = { id: videoId } 30 31 // vimeo player 作成 32 const player = new Player(iframeId, options) 33 console.log("player", player) // 切り替わっている 34 35 // 最初に1回実行 36 check(player) 37 38 let time = null 39 // タイマーでアップロード済みか確認 40 if (!uploaded) { 41 time = setInterval(() => { check(player) }, 60000) 42 } else { 43 clearInterval(time) 44 } 45 46 // アンマウント時にタイマークリア 47 return () => clearInterval(time) 48 }, [uploaded, videoId]) 49 50 return ( 51 <div 52 className="embed-container" 53 style={{ width: '100%' }} 54 > 55 <div id={iframeId}>{/* ここのidは、ページ切替時に正常に変更される */} 56 {/* Playerにより、ここにiframeが表示される¥ */} 57 {/* ↓ 表示されるiframeは、こんな感じ。ここが変更されない。 58 <iframe 59 src="https://player.vimeo.com/video/00000?title=0&byline=0&portrait=0&app_id=xxxxx" 60 width="640" height="360" 61 frameborder="0" 62 allow="autoplay; fullscreen; picture-in-picture" 63 allowfullscreen="" 64 title="xxxxxxxx" 65 data-ready="true"> 66 </iframe> 67 */} 68 </div> 69 </div> 70 ) 71} 72
投稿1つ分、表示部分
js
1// Item.js 2import React, { useEffect } from 'react' 3import { Card } from '@material-ui/core' 4import withWidth, { isWidthUp } from '@material-ui/core/withWidth' 5import { Vimeo } from './common/Vimeo' 6 7const Item = React.memo((props) => { 8 const { content } = props 9 const { key, video } = content 10 11 // video id 取得 12 const uri = video.url // https://vimeo.com/manage/videos/00000000 13 const pos = uri.lastIndexOf('/') 14 const videoId = uri.slice(pos + 1) // 00000000 15 16 return ( 17 <Card id={`item-${key}`}> 18 <p>ここにビデオが表示されます</p> 19 <Vimeo videoId={videoId} item={content} /> 20 </Card > 21 ) 22}) 23export default withWidth()(Item)
一覧ページ
js
1// Lists.js 2import React, { useState, useEffect, useContext } from 'react' 3import { List } from '@material-ui/core' 4import Pagination from '@material-ui/lab/Pagination' 5import Item from './Item' 6import { GlobalContext } from '../../hooks/reducer' 7import { itemRef } from '../../firebase' 8 9const Lists = React.memo((props) => { 10 const { state: { sample }, dispatch } = useContext(GlobalContext) 11 const { list } = sample 12 13 // ページの設定 14 const [page, setPage] = useState(1) 15 const [totalPages, setTotalPages] = useState(0) 16 const perPage = 20 17 const startNum = (page - 1) * perPage 18 19 useEffect(() => { 20 // マウント時にリストを全件取得 21 itemRef 22 .orderByKey() 23 .on('value', (snapshot) => { 24 const lists = snapshot.val() 25 if (lists === null) { return dispatch({ type: 'SET_LISTS', data: [] }) } 26 const newLists = Object.entries(lists).map((entry) => { 27 const [key, content] = entry 28 return { key, ...content } 29 }) 30 dispatch({ type: 'SET_LISTS', data: newLists }) 31 }) 32 }, []) 33 34 useEffect(() => { 35 // ページ数を取得 36 setTotalPages(Math.ceil(list.length / perPage)) 37 }, [list]) 38 39 return ( 40 <div> 41 <List> 42 { 43 list.length > 0 && ( 44 list.slice(startNum, startNum + perPage).map((content, key) => { 45 return <Item content={content} /> 46 }) 47 ) 48 } 49 </List> 50 51 {/* ページネーション */} 52 { list.length > 0 && <Pagination count={totalPages} size="large" page={page} onChange={(e, newPage) => setPage(newPage)} /> } 53 </div > 54 ) 55}) 56export default Lists
listのデータ構造
js
1list = [ 2 { 3 "key": "xxxx", 4 "video": { 5 "url": "/videos/000000" 6 }, 7 "videoUploaded": true 8 }, 9 // ... 10]
試したこと
マウント時にiframeをリロードすればいいと思い、実装しましたが、それもうまくいきません。
おそらく、読み込み完了前のためです。
エラー
TypeError: Cannot read property 'location' of undefined
js
1// Vimeo.js 2 3 // iframeをreloadする 4 const reloadIframe = (iframeId) => { 5 // フレームのDOM要素を取得 6 const target = document.getElementById(iframeId) 7 // フレームをreload 8 target.contentWindow.location.reload(true) 9 } 10 11 useEffect(() => { 12 // ....省略 13 14 reloadIframe(iframeId) 15 16 return () => clearInterval(time) 17 }, [uploaded, videoId])
onloadは効きませんでした。
js
1 const reloadIframe = (iframeId) => { 2 const target = document.getElementById(iframeId) 3 target.onload = (e) => { 4 // そもそもここに来ない 5 console.log("onloaded") 6 target.contentWindow.location.reload(true) 7 } 8 }
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。