如何在反应中呈现特定元素的弹出窗口?
How to render popup for specific element in react?
我有一个项目列表,对于每个项目 (.item-wrapper),我都想获得一个带有唯一 videoId 的视频弹出窗口。
我已经为此准备了 videoPopup 组件,但是对于每个项目,我都得到了 'elements' 数组的最后一个 'videoId'(每个项目都具有相同的 videoId)。
另一方面,当我不使用 PopupVideo 组件而只是循环遍历项目 iframe 时,我获得了特定项目的正确 ID - 这仅用于测试目的。
(注释掉的行)
我是 React 的超级新手,所以我知道这个问题可能也很容易解决。
谢谢!
显示项目的代码:
class Training extends Component {
constructor(props) {
super(props);
this.state = {
popupShowed: false
};
}
togglePopup = event => {
this.setState({
popupShowed: !this.state.popupShowed
});
};
onClosePopup = () => {
this.togglePopup();
};
content = () => {
const elements = ["76979871", "72675442", "337398380"];
const items = [];
for (const [index, value] of elements.entries()) {
items.push(
<div className="item-wrapper d-flex mb-4" key={index}>
<div className="item-col training-num text-white font-weight-normal d-flex align-items-center justify-content-center">
<span>{index < 10 ? "0" + index : index}</span>
</div>
<div className="item-col desc-col">
<h3 className="text-white title font-weight-normal">
Dlaczego warto?
</h3>
<div className="text-wrapper training-desc text-white">
<p>
Dowiesz się dlaczego Social Media Ninja to Zawód Przyszłości.
Dostaniesz wiedzę na temat oferowania i briefowania klientów i
dowiesz się jak zarabiać na social mediach.
</p>
</div>
</div>
<div className="item-col text-white time-col">
<div className="inside-wrapper">
<p className="text-nowrap">
<strong>Czas trwania:</strong> 2:25:00
<br />
<strong>Twój postęp:</strong> 90%
</p>
</div>
</div>
<div className="item-col play-col d-flex align-items-center justify-content-center d-flex align-items-center justify-content-center">
<div className="play-wrapper" onClick={this.togglePopup}>
<svg
enableBackground="new 0 0 60.001 60.001"
viewBox="0 0 60.001 60.001"
xmlns="http://www.w3.org/2000/svg"
className="play-button"
>
<path d="m59.895 58.531-29-58c-.34-.678-1.449-.678-1.789 0l-29 58c-.155.31-.139.678.044.973.182.294.504.474.85.474h58c.347 0 .668-.18.851-.474.182-.295.199-.663.044-.973zm-57.277-.553 27.382-54.764 27.382 54.764z" />
</svg>
<span className="text-white mt-2 d-inline-block">zobacz</span>
{/* <iframe src={'https://player.vimeo.com/video/' + value} width="500" height="600" frameBorder="0" allowFullScreen mozallowfullscreen="true" allowFullScreen></iframe> */}
</div>
</div>
{this.state.popupShowed ? (
<PopupVideo videoId={value} closePopup={this.onClosePopup} />
) : null}
</div>
);
}
return <div className="list-wrapper">{items}</div>;
};
render() {
return <Layout content={this.content()} />;
}
}
export default Training;
显示popupVideo的代码:
class PopupVideo extends Component {
componentDidMount = () => {
var iframe = document.querySelector("iframe");
var player = new Player(iframe);
player.on("play", function() {
console.log("played the video!");
});
};
render() {
return (
<div className="popup video-popup">
<div className="popup-inner d-flex align-items-center d-flex justify-content-center">
<div className="video">
<span
onClick={this.props.closePopup}
className="close-video d-flex align-items-center justify-content-center"
>
<img
src="https://rahimblak.com/images/video-close.png"
alt="close video"
/>
</span>
<div className="embed-container">
<iframe
src={
"https://player.vimeo.com/video/" +
this.props.videoId +
"?api=1&autoplay=0#t=0"
}
title="Nazwa szkolenia"
frameBorder="0"
allowFullScreen
mozallowfullscreen="true"
allowFullScreen
></iframe>
</div>
<div className="video-nav">
<div className="video-progress"></div>
<div className="d-flex align-items-center py-4">
<div className="play">
<span className="play-video"></span>
</div>
<div className="stop">
<span className="stop-video"></span>
</div>
<div className="volume">
<span className="volume-video"></span>
</div>
<div className="time">00:00 / 05:50</div>
<div className="break"></div>
<div className="title">
<h4>
<strong className="mr-3 pr-3">01</strong>Dlaczego warto ?
</h4>
</div>
<div className="button">
<button className="btn btn-secondary d-flex justify-content-center text-uppercase text-light font-weight-bold px-4">
Zobacz następny
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default PopupVideo;
我在控制台中没有任何错误消息。
好的,我简化了组件以向您展示处理此类问题的良好模式。
首先创建一个VideoContainer
来容纳state
中的所有videoIds
。
我们将 return 一个包含 Video
个组件的数组,并将 videoId
作为 props 传递给每个组件。
这个容器将负责只向其他组件提供数据
class VideoContainer extends Component {
state = {
videoIds: ["76979871", "72675442", "337398380"]
};
renderVideo = videoId => <Video key={videoId} videoId={videoId} />
render() {
const { videoIds } = this.state;
return videoIds.map(this.renderVideo);
}
}
然后创建一个 Video
组件,它将在 state
中包含 popupShowed
并且仅当 popupShowed
为 [=23] 时才会包含 PopupVideo
组件=] 使用 &&
传入 videoId
和 togglePopup
处理程序作为 props
.
现在每个 Video
都是一个独立的组件,其中包含 state
用于显示 PopupVideo
class Video extends Component {
state = {
popupShowed: false
};
togglePopup = () => {
this.setState(prevState => ({
popupShowed: !prevState.popupShowed
}));
};
render() {
const { popupShowed } = this.state;
const { videoId } = this.props;
return (
<div className="item-wrapper d-flex mb-4">
<button onClick={this.togglePopup}>Show Popup</button>
{popupShowed && (
<PopupVideo videoId={videoId} closePopup={this.togglePopup} />
)}
</div>
);
}
}
最后 PopupVideo
const PopupVideo = ({ videoId, closePopup }) => (
<div className="popup video-popup">
<span onClick={closePopup}>
<img
src="https://rahimblak.com/images/video-close.png"
alt="close video"
/>
</span>
<div className="embed-container">
<iframe
src={
"https://player.vimeo.com/video/" +
videoId +
"?api=1&autoplay=0#t=0"
}
title="Nazwa szkolenia"
frameBorder="0"
allowFullScreen
mozallowfullscreen="true"
/>
</div>
</div>
);
我有一个项目列表,对于每个项目 (.item-wrapper),我都想获得一个带有唯一 videoId 的视频弹出窗口。
我已经为此准备了 videoPopup 组件,但是对于每个项目,我都得到了 'elements' 数组的最后一个 'videoId'(每个项目都具有相同的 videoId)。
另一方面,当我不使用 PopupVideo 组件而只是循环遍历项目 iframe 时,我获得了特定项目的正确 ID - 这仅用于测试目的。 (注释掉的行)
我是 React 的超级新手,所以我知道这个问题可能也很容易解决。
谢谢!
显示项目的代码:
class Training extends Component {
constructor(props) {
super(props);
this.state = {
popupShowed: false
};
}
togglePopup = event => {
this.setState({
popupShowed: !this.state.popupShowed
});
};
onClosePopup = () => {
this.togglePopup();
};
content = () => {
const elements = ["76979871", "72675442", "337398380"];
const items = [];
for (const [index, value] of elements.entries()) {
items.push(
<div className="item-wrapper d-flex mb-4" key={index}>
<div className="item-col training-num text-white font-weight-normal d-flex align-items-center justify-content-center">
<span>{index < 10 ? "0" + index : index}</span>
</div>
<div className="item-col desc-col">
<h3 className="text-white title font-weight-normal">
Dlaczego warto?
</h3>
<div className="text-wrapper training-desc text-white">
<p>
Dowiesz się dlaczego Social Media Ninja to Zawód Przyszłości.
Dostaniesz wiedzę na temat oferowania i briefowania klientów i
dowiesz się jak zarabiać na social mediach.
</p>
</div>
</div>
<div className="item-col text-white time-col">
<div className="inside-wrapper">
<p className="text-nowrap">
<strong>Czas trwania:</strong> 2:25:00
<br />
<strong>Twój postęp:</strong> 90%
</p>
</div>
</div>
<div className="item-col play-col d-flex align-items-center justify-content-center d-flex align-items-center justify-content-center">
<div className="play-wrapper" onClick={this.togglePopup}>
<svg
enableBackground="new 0 0 60.001 60.001"
viewBox="0 0 60.001 60.001"
xmlns="http://www.w3.org/2000/svg"
className="play-button"
>
<path d="m59.895 58.531-29-58c-.34-.678-1.449-.678-1.789 0l-29 58c-.155.31-.139.678.044.973.182.294.504.474.85.474h58c.347 0 .668-.18.851-.474.182-.295.199-.663.044-.973zm-57.277-.553 27.382-54.764 27.382 54.764z" />
</svg>
<span className="text-white mt-2 d-inline-block">zobacz</span>
{/* <iframe src={'https://player.vimeo.com/video/' + value} width="500" height="600" frameBorder="0" allowFullScreen mozallowfullscreen="true" allowFullScreen></iframe> */}
</div>
</div>
{this.state.popupShowed ? (
<PopupVideo videoId={value} closePopup={this.onClosePopup} />
) : null}
</div>
);
}
return <div className="list-wrapper">{items}</div>;
};
render() {
return <Layout content={this.content()} />;
}
}
export default Training;
显示popupVideo的代码:
class PopupVideo extends Component {
componentDidMount = () => {
var iframe = document.querySelector("iframe");
var player = new Player(iframe);
player.on("play", function() {
console.log("played the video!");
});
};
render() {
return (
<div className="popup video-popup">
<div className="popup-inner d-flex align-items-center d-flex justify-content-center">
<div className="video">
<span
onClick={this.props.closePopup}
className="close-video d-flex align-items-center justify-content-center"
>
<img
src="https://rahimblak.com/images/video-close.png"
alt="close video"
/>
</span>
<div className="embed-container">
<iframe
src={
"https://player.vimeo.com/video/" +
this.props.videoId +
"?api=1&autoplay=0#t=0"
}
title="Nazwa szkolenia"
frameBorder="0"
allowFullScreen
mozallowfullscreen="true"
allowFullScreen
></iframe>
</div>
<div className="video-nav">
<div className="video-progress"></div>
<div className="d-flex align-items-center py-4">
<div className="play">
<span className="play-video"></span>
</div>
<div className="stop">
<span className="stop-video"></span>
</div>
<div className="volume">
<span className="volume-video"></span>
</div>
<div className="time">00:00 / 05:50</div>
<div className="break"></div>
<div className="title">
<h4>
<strong className="mr-3 pr-3">01</strong>Dlaczego warto ?
</h4>
</div>
<div className="button">
<button className="btn btn-secondary d-flex justify-content-center text-uppercase text-light font-weight-bold px-4">
Zobacz następny
</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default PopupVideo;
我在控制台中没有任何错误消息。
好的,我简化了组件以向您展示处理此类问题的良好模式。
首先创建一个VideoContainer
来容纳state
中的所有videoIds
。
我们将 return 一个包含 Video
个组件的数组,并将 videoId
作为 props 传递给每个组件。
这个容器将负责只向其他组件提供数据
class VideoContainer extends Component {
state = {
videoIds: ["76979871", "72675442", "337398380"]
};
renderVideo = videoId => <Video key={videoId} videoId={videoId} />
render() {
const { videoIds } = this.state;
return videoIds.map(this.renderVideo);
}
}
然后创建一个 Video
组件,它将在 state
中包含 popupShowed
并且仅当 popupShowed
为 [=23] 时才会包含 PopupVideo
组件=] 使用 &&
传入 videoId
和 togglePopup
处理程序作为 props
.
现在每个 Video
都是一个独立的组件,其中包含 state
用于显示 PopupVideo
class Video extends Component {
state = {
popupShowed: false
};
togglePopup = () => {
this.setState(prevState => ({
popupShowed: !prevState.popupShowed
}));
};
render() {
const { popupShowed } = this.state;
const { videoId } = this.props;
return (
<div className="item-wrapper d-flex mb-4">
<button onClick={this.togglePopup}>Show Popup</button>
{popupShowed && (
<PopupVideo videoId={videoId} closePopup={this.togglePopup} />
)}
</div>
);
}
}
最后 PopupVideo
const PopupVideo = ({ videoId, closePopup }) => (
<div className="popup video-popup">
<span onClick={closePopup}>
<img
src="https://rahimblak.com/images/video-close.png"
alt="close video"
/>
</span>
<div className="embed-container">
<iframe
src={
"https://player.vimeo.com/video/" +
videoId +
"?api=1&autoplay=0#t=0"
}
title="Nazwa szkolenia"
frameBorder="0"
allowFullScreen
mozallowfullscreen="true"
/>
</div>
</div>
);