useEffect 在 useFrameApi onReady 事件中不起作用
useEffect not working in useFrameApi onReady event
我正在尝试使用 useEffect Hook 动态更改视频的 url,我不想使用第三方库,所以我已经完成了这个脚本,当我更改 url 时, youtubeId 状态更新良好,但播放器中没有加载新视频。
import React, { useEffect, useState } from "react";
const Y = () => {
const [youtubeId, setYoutubeId] = useState("ZPt9dJw1Dbw");
useEffect(() => {
if (!window.YT) {
// If not, load the script asynchronously
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
// onYouTubeIframeAPIReady will load the video after the script is loaded
window.onYouTubeIframeAPIReady = loadVideo;
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
} else {
loadVideo();
}
function loadVideo() {
console.log(youtubeId);
let player = new window.YT.Player(`youtube-player-${youtubeId}`, {
videoId: youtubeId,
events: {
onReady: (event) => {
event.target.playVideo();
event.target.loadVideoById({
videoId: youtubeId
});
}
}
});
}
//
}, [youtubeId]);
const foo = () => {
setYoutubeId("ZrNqjSCfL8E");
};
return (
<div>
<div id={`youtube-player-${youtubeId}`} />
<button onClick={foo}>change video</button>
</div>
);
};
export default Y;
您已正确完成大部分工作。如果你通过 youtube Iframe api 他们设置全局 var
。这意味着你必须做一些改变。
- 在外部定义
player
变量。
- 根据您的代码,它将重试在变量中设置
new window.YT.Player
对象,但这不是 Iframe api 的工作方式。一旦它设置在您的 player
对象中。它将提供另一个 useFull 函数来执行此操作(您可以在文档中找到)。
完整代码如下:
import { useEffect, useState, useCallback } from "react";
import "./styles.css";
// import React, { useEffect, useState } from "react";
let player;
const Y = () => {
const [youtubeId, setYoutubeId] = useState("ZPt9dJw1Dbw");
useEffect(() => {
if (!window.YT) {
// If not, load the script asynchronously
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
// onYouTubeIframeAPIReady will load the video after the script is loaded
window.onYouTubeIframeAPIReady = loadVideo;
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
} else {
loadVideo();
}
function loadVideo() {
if (!player) {
player = new window.YT.Player(`youtube-player-${youtubeId}`, {
videoId: youtubeId,
events: {
onReady: (event) => {
event.target.playVideo();
event.target.loadVideoById({
videoId: youtubeId
});
}
}
});
}
if (player && player.loadVideoById) {
player.loadVideoById({ videoId: youtubeId });
}
}
//
}, [youtubeId]);
const foo = () => {
setYoutubeId("ZrNqjSCfL8E");
};
return (
<div>
<div id={`youtube-player-${youtubeId}`} />
<button onClick={foo}>change video</button>
</div>
);
};
export default function App() {
return (
<div className="App">
<Y />
</div>
);
}
我正在尝试使用 useEffect Hook 动态更改视频的 url,我不想使用第三方库,所以我已经完成了这个脚本,当我更改 url 时, youtubeId 状态更新良好,但播放器中没有加载新视频。
import React, { useEffect, useState } from "react";
const Y = () => {
const [youtubeId, setYoutubeId] = useState("ZPt9dJw1Dbw");
useEffect(() => {
if (!window.YT) {
// If not, load the script asynchronously
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
// onYouTubeIframeAPIReady will load the video after the script is loaded
window.onYouTubeIframeAPIReady = loadVideo;
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
} else {
loadVideo();
}
function loadVideo() {
console.log(youtubeId);
let player = new window.YT.Player(`youtube-player-${youtubeId}`, {
videoId: youtubeId,
events: {
onReady: (event) => {
event.target.playVideo();
event.target.loadVideoById({
videoId: youtubeId
});
}
}
});
}
//
}, [youtubeId]);
const foo = () => {
setYoutubeId("ZrNqjSCfL8E");
};
return (
<div>
<div id={`youtube-player-${youtubeId}`} />
<button onClick={foo}>change video</button>
</div>
);
};
export default Y;
您已正确完成大部分工作。如果你通过 youtube Iframe api 他们设置全局 var
。这意味着你必须做一些改变。
- 在外部定义
player
变量。 - 根据您的代码,它将重试在变量中设置
new window.YT.Player
对象,但这不是 Iframe api 的工作方式。一旦它设置在您的player
对象中。它将提供另一个 useFull 函数来执行此操作(您可以在文档中找到)。
完整代码如下:
import { useEffect, useState, useCallback } from "react";
import "./styles.css";
// import React, { useEffect, useState } from "react";
let player;
const Y = () => {
const [youtubeId, setYoutubeId] = useState("ZPt9dJw1Dbw");
useEffect(() => {
if (!window.YT) {
// If not, load the script asynchronously
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
// onYouTubeIframeAPIReady will load the video after the script is loaded
window.onYouTubeIframeAPIReady = loadVideo;
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
} else {
loadVideo();
}
function loadVideo() {
if (!player) {
player = new window.YT.Player(`youtube-player-${youtubeId}`, {
videoId: youtubeId,
events: {
onReady: (event) => {
event.target.playVideo();
event.target.loadVideoById({
videoId: youtubeId
});
}
}
});
}
if (player && player.loadVideoById) {
player.loadVideoById({ videoId: youtubeId });
}
}
//
}, [youtubeId]);
const foo = () => {
setYoutubeId("ZrNqjSCfL8E");
};
return (
<div>
<div id={`youtube-player-${youtubeId}`} />
<button onClick={foo}>change video</button>
</div>
);
};
export default function App() {
return (
<div className="App">
<Y />
</div>
);
}