#reactjs #react-hooks
#reactjs #реагирующие перехваты
Вопрос:
const VideoList = ({ videoList }) => {
let stateArr:any=[]
for(let i=0;i<content.videoListItems.length;i ){
stateArr[i]=true
}
const [iconDisplay, setIconHide] = useState(stateArr);
const stopVideo=(e:any,index:any)=>{
stateArr[index]=true
e.target.parentElement.parentElement.previousSibling.pause();
}
const videoPlay=(e:any,index:any)=>{
stateArr[index]=false
e.target.parentElement.parentElement.previousSibling.play();
}
useEffect(() => {
setIconHide(stateArr);
}, []);
return (
<div>
{videoListItems.map((item: any, index: number) => { //rendering video list
return (
<div key={index}>
<video src={item.video.url} />
<span>
{iconDisplay[index] amp;amp;<button onClick={(e:any)=>videoPlay(e,index)}>
<img // rendering play image
src="play.svg"
alt="Play Icon"
/>
</button>}
{!iconDisplay[index] amp;amp; <button onClick={(e:any)=>stopVideo(e,index)}>
<img
src="pause.svg" //rendering pause image
alt="Pause Icon"
/>
</button>
}
</span>
</div>
)
})
}
</div>
)
}
Как я могу добиться этой функциональности? Я пытаюсь отобразить список видео и, основываясь на событии, нажимаю, пытаясь воспроизвести и приостановить, но почему-то я не могу отобразить изображение на паузе после 1-го щелчка
Комментарии:
1. Ваш
let stateArr=[]
иfor all i's make stateArr[i] = true
находится в цикле рендеринга. Этот код будет выполняться каждый раз при повторном рендеринге компонента, поэтому он не будет обновляться, как вы ожидаете. stateArr, вероятно, должен быть состоянием реакции (useState), и вы захотите обновить, создав новый объект stateArr, не изменяя оригинал.2. Есть ли какая-либо причина, по которой вам может потребоваться узнать, какие видео в списке воспроизводятся? Вместо обновления элемента в массиве, я думаю, было бы намного проще, если бы вы отображали каждое видео через
Video
компонент, который управляет его собственным состоянием паузы / воспроизведения.
Ответ №1:
Вы делаете это слишком сложным, управляя своим состоянием в array
. Это можно сделать, но изменять состояние с помощью настройки stateArr[index]=true
— это не выход.
Вы можете сделать это намного проще для себя, если у вас есть Video
компонент для каждого видео в списке, который внутренне обрабатывает свое собственное isPlaying
состояние.
Я использую a ref
для доступа к элементу video, а не для просмотра отношений DOM parent / sibling.
import { useState, useRef } from "react";
type VideoProps = {
src: string; // require an src
} amp; JSX.IntrinsicElements["video"]; // allow any other props of the HTML <video> element
const Video = (props: VideoProps) => {
const videoRef = useRef<HTMLVideoElement>(null);
const [isPlaying, setIsPlaying] = useState(false);
const togglePlay = () => {
// play or pause the video element
if (isPlaying) {
videoRef.current?.pause();
} else {
videoRef.current?.play();
}
// update the state
setIsPlaying(!isPlaying);
};
return (
<div>
<video
{...props} // pass through all props to the video element
ref={videoRef} // attach the ref
/>
<span>
<button onClick={togglePlay}>
<img
src={isPlaying ? "pause.svg" : "play.svg"}
alt={isPlaying ? "Pause" : "Play"}
/>
</button>
</span>
</div>
);
};
type VideoListProps = {
videoListItems: Array<{
video: {
url: string;
};
}>;
};
const VideoList = ({ videoListItems }: VideoListProps) => {
return (
<div>
{videoListItems.map((item) => (
<Video key={item.video.url} src={item.video.url} />
))}
</div>
);
};