Предварительный просмотр загрузки файлов React исчезает при переключении вкладок (состояние сохраняется)Javascript

Форум по Javascript
Ответить Пред. темаСлед. тема
Anonymous
 Предварительный просмотр загрузки файлов React исчезает при переключении вкладок (состояние сохраняется)

Сообщение Anonymous »

Я строю систему загрузки файлов в моем приложении React, где пользователи могут загружать видео, изображения или субтитры. Файлы загружаются с использованием пользовательского компонента , который генерирует предварительный просмотр выбранного файла с использованием url.createObjecturl () . Однако, когда я переключаю вкладки и возвращаюсь в раздел загрузки файла, предварительный просмотр файла исчезает, но URL -файл все еще существует в состоянии React. < /P>
Что я хочу: < /p>

✅ Я хочу предварительный просмотр файла. Должен
загрузить из URL без повторной загрузки файла. < /li>
✅ < /li>
< /ol>
🐛current Поведение (ошибка):
Когда я загружаю файл (видео, изображение или подзаголовок), он мгновенно показывает, что предварительно выключает в таблице. исчезает, но URL -файл все еще находится в состоянии (uploaddetails).
Если я снова нажимаю на загрузку, форма все еще содержит правильный URL -адрес файла - это просто предварительный просмотр, который исчезает. Предоставляя все мои межсековые файлы, поэтому, пожалуйста, помогите мне исправить это
Проблема в видео :: gdrive
Полный код: код
Strong>showupload.jsx
Strong>showupload.jsx>
import { useEffect, useState } from "react";
import { Separator } from "@/components/ui/separator";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { ShowBasicDetails } from "./tabs/ShowBasicDetails";
import { ShowFileUpload } from "./tabs/showFileUpload";
import { ScrollArea } from "../../ui/scroll-area";
import { Button } from "../../ui/button";
import { toast } from "react-hot-toast";
import {
FINAL_initialState,
FINAL_showVideoInitialFormData,
} from "../../../config/formFields";

export const ShowUpload = () => {
const [activeTab, setActiveTab] = useState("showDetails");
const [showDetailsData, setShowDetailsData] = useState(FINAL_initialState);
const [UploadDetailsData, setUploadDetailsData] = useState({});
const [category, setCategory] = useState("");

useEffect(() => {
setCategory(showDetailsData.category);
}, [showDetailsData.category]);

const handleNext = () => {
if (activeTab === "showDetails") {
// if (!category) {
// toast.error("Please select a category first.");
// return;
// }
setActiveTab("showUpload");
}
};

const handlePrevious = () => {
if (activeTab === "showUpload") {
setActiveTab("showDetails");
}
};

const handleCancel = () => {
toast.success("Upload Cancelled.");
setShowDetailsData(FINAL_initialState);
setUploadDetailsData({});
};

const handleUpload = () => {
const payload = {
...showDetailsData,
...UploadDetailsData,
};
console.log("FINAL DATA TO BACKEND: ✅🔥", payload);
toast.success("Show Uploaded Successfully! 🎉");
};

return (

{/* ✅ Tabs */}

setActiveTab(val)}
className="w-[400px]"
>

Show Details
Show Upload






{activeTab === "showDetails" && (

)}
{activeTab === "showUpload" && (

)}


{activeTab === "showDetails" && (


Cancel


Next


)}
{activeTab === "showUpload" && (


Previous

Upload

)}


);
};


showbasicdetails.jsx
/* eslint-disable react/prop-types */
import { FINAL_showBasicFormControls } from "../../../../config/formFields";
import { AdminForm } from "../../../common/common-Form/adminForm";

export const ShowBasicDetails = ({ showDetails, setShowDetails }) => {
return (

Details


);
};


showfileupload.jsx
import { useEffect, useState } from "react";
import { Button } from "../../../ui/button";
import { Label } from "../../../ui/label";
import { Input } from "../../../ui/input";
import { X } from "lucide-react";
import { toast } from "react-hot-toast";
import { AdminFileUpload } from "../../../common/common-Form/adminFileUpload";

export const ShowFileUpload = ({
category,
UploadDetails,
setUploadDetails,
}) => {
const [episodes, setEpisodes] = useState([
{ title: "", video: null, subtitle: null },
]);
const [movie, setMovie] = useState({
video: null,
subtitle: null,
});

// ✅ Reset Data When Category Changes 🔥
useEffect(() => {
if (category === "movie") {
setMovie({ video: null, subtitle: null });
setUploadDetails({ movie: { video: null, subtitle: null } });
} else {
setEpisodes([{ title: "", video: null, subtitle: null }]);
setUploadDetails({
episodes: [{ title: "", video: null, subtitle: null }],
});
}
}, [category]);

// ✅ Sync Movie Data With Parent 🔥
useEffect(() => {
if (category === "movie") {
setUploadDetails({ movie });
}
}, [movie]);

// ✅ Sync Episode Data With Parent 🔥
useEffect(() => {
if (category === "webseries") {
setUploadDetails({ episodes });
}
}, [episodes]);

// ✅ Handle Add Episode 🔥
const handleAddEpisode = () => {
setEpisodes([...episodes, { title: "", video: null, subtitle: null }]);
};

// ✅ Handle Remove Episode 🔥
const handleRemoveEpisode = (index) => {
if (episodes.length === 1) {
toast.error("At least one episode is mandatory.");
return;
}
const updatedEpisodes = episodes.filter((_, i) => i !== index);
setEpisodes(updatedEpisodes);
};

// ✅ Handle File & Text Change 🔥
const handleChange = (index, field, value) => {
const updatedEpisodes = [...episodes];
updatedEpisodes[index][field] = value;
setEpisodes(updatedEpisodes);
};

// ✅ Handle Video Removal 🔥
const handleRemoveVideo = (index) => {
const updatedEpisodes = [...episodes];
updatedEpisodes[index].video = null;
setEpisodes(updatedEpisodes);
};

if (!category) {
return "Choose Category";
}

return (


{category === "movie" ? "Upload Movie & Subtitle" : "Upload Episodes"}


{/* ✅ IF CATEGORY IS MOVIE */}
{category === "movie" ? (

Upload Movie
setMovie((prev) => ({ ...prev, video: file }))}
/>

Upload Subtitle

setMovie((prev) => ({ ...prev, subtitle: file }))
}
/>

) : (


+ Add Episode

{/* ✅ LOOP THROUGH EPISODES */}
{episodes.map((episode, index) => (
key={index}
className="p-4 border rounded-md bg-gray-800 mb-4 relative"
>
{/* ✅ REMOVE BUTTON AT TOP RIGHT */}

{index > 0 && (
handleRemoveEpisode(index)}
>
Remove

)}

{/* ✅ EPISODE TITLE */}
Episode {index + 1}
handleChange(index, "title", e.target.value)}
placeholder={`Episode ${index + 1} Title`}
/>

{/* ✅ VIDEO UPLOAD */}
Upload Video
handleChange(index, "video", file)}
/>

{/* ✅ VIDEO PREVIEW */}
{episode.video && episode.video instanceof File && (

handleRemoveVideo(index)}
>



)}

{/* ✅ SUBTITLE UPLOAD */}
Upload Subtitle
handleChange(index, "subtitle", file)}
/>

))}

)}

);
};


adminfileupload.jsx
/* eslint-disable react/prop-types */
import { FileIcon, UploadCloudIcon, XIcon } from "lucide-react";
import { Input } from "../../ui/input";
import { useRef, useState } from "react";
import { toast } from "react-hot-toast";

export const AdminFileUpload = ({
onUpload = () => {}, // ✅ It will directly pass fileUrl to FormData
accept = "image/*,video/*,.srt,.vtt",
text = "Upload File",
}) => {
const [file, setFile] = useState(null);
const inputRef = useRef(null);

// ✅ Handle File Upload Click
function handleClick() {
if (inputRef.current) inputRef.current.click();
}

// ✅ Handle File Selection
function handleFileChange(event) {
const selectedFile = event.target.files[0];
if (!selectedFile) {
toast.error("❌ File Upload Failed!");
return;
}

// ✅ Reset Input Lock
event.target.value = "";

// ✅ Generate File URL
const fileUrl = URL.createObjectURL(selectedFile);

// ✅ Save File State
setFile({
name: selectedFile.name,
url: fileUrl,
type: selectedFile.type,
size: selectedFile.size,
raw: selectedFile,
});

// ✅ Pass File URL Directly to FormData
onUpload(fileUrl);

// ✅ Show Confirmation Based on File Type
if (selectedFile.type.startsWith("video/")) {
toast.success("✅ Video File Selected!");
} else if (
selectedFile.name.endsWith(".srt") ||
selectedFile.name.endsWith(".vtt")
) {
toast.success("✅ Subtitle File Selected!");
} else {
toast.success(`✅ ${selectedFile.name} Uploaded Successfully!`);
}
}

// ✅ Handle File Removal
function handleRemoveFile(event) {
event.stopPropagation();
setFile(null);
onUpload(""); // ✅ Pass Empty URL to FormData
toast.success("File Removed Successfully!");
}

return (

{/* ✅ UPLOAD BOX */}



{/* ✅ FILE PREVIEW INSIDE BOX */}
{file ? (

{/* ✅ REMOVE BUTTON INSIDE THE BOX */}



{/* ✅ IF IMAGE */}
{file.type.startsWith("image/") && (
[img]{file.url}
className="w-full h-[150px] object-none rounded-lg "
/>
)}

{/* ✅ IF VIDEO */}
{file.type.startsWith("video/") && (

)}

{/* ✅ IF SUBTITLE */}
{(file.name.endsWith(".srt") || file.name.endsWith(".vtt")) && (



{file.name}


)}

) : (

{/* ✅ DEFAULT UPLOAD AREA */}

Click to select {text}

)}


);
};


adminform.jsx
/* eslint-disable no-undef */
/* eslint-disable react-refresh/only-export-components */
/* eslint-disable react/prop-types */

import { Input } from "../../ui/input";
import { Label } from "../../ui/label";
import { Button } from "../../ui/button";
import { Textarea } from "../../ui/textarea";
import { ToggleGroup, ToggleGroupItem } from "../../ui/toggle-group";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "../../ui/select";
import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover";
import { Calendar } from "../../ui/calendar";
import { AdminFileUpload } from "./adminFileUpload";

export const AdminForm = ({ formControls = [], formData, setFormData }) => {
// Function to render inputs dynamically based on component type
function renderInputsByComponentType(getControlItem) {
let element = null;
const value = formData[getControlItem.name] || "";

switch (getControlItem.componentType) {
// Input Field
case "input":
element = (

setFormData({
...formData,
[getControlItem.name]: event.target.value,
})
}
/>
);
break;

// Select Dropdown
case "select":
element = (

setFormData({ ...formData, [getControlItem.name]: value })
}
value={value}
>




{getControlItem.options &&
getControlItem.options.map((optionItem) => (

{optionItem.label}

))}


);
break;

case "textarea":
element = (

setFormData({
...formData,
[getControlItem.name]: event.target.value,
})
}
/>
);
break;
// Toggle Group (Genre Selection)

case "toggle-group":
element = (

{getControlItem.options.map((optionItem) => (

{optionItem.label}

))}

);
break;

// Date Picker (Better Date Format)
case "date":
element = (



{formData[getControlItem.name]
? new Date(formData[getControlItem.name]).toLocaleDateString()
: "Pick a date"}



{
if (selectedDate) {
setFormData({
...formData,
[getControlItem.name]: selectedDate
.toISOString()
.split("T")[0], // Saves as YYYY-MM-DD
});
}
}}
initialFocus
/>


);
break;

// File Upload (Dynamic Accept Type)
case "file":
element = (

setFormData({
...formData,
[getControlItem.name]: fileUrl,
})
}
/>
);
break;

default:
element = (

setFormData({
...formData,
[getControlItem.name]: event.target.value,
})
}
/>
);
break;
}
return element;
}

return (

{formControls.map((controleItem) => (

{controleItem.label}
{renderInputsByComponentType(controleItem)}

))}

);
};



Подробнее здесь: https://stackoverflow.com/questions/794 ... e-persists
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Javascript»