У меня проблемы с доступом к идентификатору кнопки непосредственно после ее создания с помощью функции .map () ....
Вот нижний предел ... Я постараюсь сделать это проще -
Пользователь вводит URL-адрес YouTube во вход.
Функция onClick handleAddVideo () выполняет две функции. Он извлекает идентификатор видео YouTube из URL-адреса и сохраняет этот URL-адрес в состоянии, называемом videoLinks.
В моем рендере я сопоставляю массив с состоянием videoLinks, и он автоматически встраивает их в профиль пользователя с помощью кнопки для удаления видео.
Кнопка удаления имеет функцию onClick, которая использует идентификатор кнопки (такой же, как идентификатор видео), чтобы найти и удалить видео из состояния.
Это работает, за исключением одной проблемы ... страница должна быть перезагружена, чтобы кнопка отправила идентификатор функции удаления. Если пользователь отправляет ссылку и публикует видео, не обновляя страницу, он выдает TypeError: Cannot read свойство 'id' из null. Если страница перезагружена - все работает нормально. Спасибо за вашу помощь!
import React, { useState, useEffect } from 'react';
import { useAuth0 } from "../../../react-auth0-spa";
import { Input, Card, Button, CardTitle
} from 'reactstrap';
let saveLinks = true
export default function VideoCard(props) {
const [ linkHolder, setVideoLinkHolder ] = useState('')
const [ videoLinks, setVideoLinks ] = useState([]);
const { getTokenSilently } = useAuth0();
useEffect(() => {
getOldVideoLinks();
}, [])
useEffect(() => {
if(saveLinks){
setTimeout(() => {
saveLinks = false
},300)
}else {
saveVideoLinks();
}
}, [videoLinks])
const getOldVideoLinks = async () => {
const token = await getTokenSilently();
try {
const response = await fetch(`/api/autoquotegenerators/${props._id}`, {
headers: {
Authorization: `bearer ${token}`,
"Content-Type": "application/json; charset=UTF-8",
}
});
const responseData = await response.json()
setVideoLinks(responseData.youtube)
} catch (error) {
console.log(error)
}
}
const handleAddVideoLink = (e) => {
setVideoLinkHolder(e.target.value);
}
const handleAddVideo = () => {
if(videoLinks.length < 4){
if(linkHolder){
var regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var match = linkHolder.match(regExp);
if (match && match[2].length == 11) {
console.log(match[2])
return setVideoLinks((videoLinks) => [...videoLinks, match[2]]);
} else {
alert('Sorry! Please use a valid Youtube URL.')
}
}else {
alert('Copy and Paste a Youtube Link Before Submitting!')
}
}else {
alert('You have reached the maximum number of videos for this band.')
}
}
const saveVideoLinks = async () => {
const token = await getTokenSilently();
try {
const response = await fetch(`/api/autoquotegenerators/${props._id}`, {
method: 'PUT',
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json; charset=UTF-8",
},
body: JSON.stringify({youtube: videoLinks})
})
const responseData = response.json()
} catch (error) {
console.log(error)
}
}
const deleteVideo = (e) => {
setVideoLinks((videoLinks) => [
...videoLinks.filter(link => {
return link !== e.target.id
}),
]);
}
const createVideoCard = (link) => {
return (
<div className="mb-1 d-flex flex-column w-100 justify-content-center">
<div
className="video"
style={{
position: "relative",
paddingBottom: "56.25%" /* 16:9 */,
// paddingTop: 25,
height: 0,
}}>
<Button id={link} onClick={deleteVideo} style={{zIndex: "2"}} color="danger" size="sm" className="col-1 m-1 position-absolute">x</Button>
<iframe
style={{
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%",
pointerEvents: "none",
borderRadius: "5px",
filter: "opacity(.5)",
}}
src={`https://www.youtube.com/embed/${link}`}
frameBorder="0"
/>
</div>
</div>
)
}
return (
<div className="d-flex flex-column justify-content-center">
{videoLinks.map(link => {
const vidCard = createVideoCard(link)
return <div key={link}>{vidCard}</div>
})}
<Card color="dark" className="my-1 py-3 d-flex flex-column w-100 justify-content-center">
<CardTitle className="align-self-center text-center text-light w-75 mb-1"><h4>Video Link</h4></CardTitle>
<Input onChange={handleAddVideoLink} placeholder="Paste Youtube Link!" type="url" className="w-75 mb-1 align-self-center"></Input>
<Button onClick={handleAddVideo} className="align-self-center text-center text-light w-75"><h4>Add Video</h4></Button>
</Card>
</div>
)
}