I only came across very hacky solutions, so maybe someone has a better idea how to solve it.
Here's what I'm trying to do:
- The
UploadComponentlets the user select files usingrefs. - Once a file is selected, it’s passed to the parent component (App), which keeps track of the uploaded files.
- The
FilePreviewComponentdisplays the uploaded files and allows the user to delete a file. When a file is deleted, I want to reset the file input refs in the UploadComponent so that the same file can be uploaded again.
For now I couldn't find any solution to reset refs cross-component. Here is code example:
const App = () => {
const { control, handleSubmit, setValue, getValues } = useForm();
const [selectedFiles, setSelectedFiles] = useState([]);
const onSubmit = (data) => {
console.log(data);
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* Upload Component */}
<Controller
name="files"
control={control}
render={({ field: { value, onChange } }) => (
<UploadComponent
onFileSelected={(files) => {
const updatedFiles = [...value, ...files];
onChange(updatedFiles);
setSelectedFiles(updatedFiles);
}}
/>
)}
/>
{/* File Preview Component */}
<Controller
name="files"
control={control}
render={({ field: { value } }) => (
<FilePreviewComponent
files={value}
onDelete={(fileToDelete) => {
const updatedFiles = value.filter((file) => file.uri !== fileToDelete.uri);
setSelectedFiles(updatedFiles);
setValue("files", updatedFiles);
}}
/>
)}
/>
<button type="submit">Submit</button>
</form>
);
};
export default App;
And here is the upload component.
const UploadComponent = ({ onFileSelected }) => {
const fileInputRef = useRef(null);
const handleFileUpload = (e) => {
const files = Array.from(e.target.files).map((file) => ({
uri: URL.createObjectURL(file), // Create a temporary URL for preview
name: file.name,
type: file.type,
blob: file,
}));
onFileSelected(files);
};
return (
<div>
{/* Button to trigger file input */}
<button onClick={() => fileInputRef.current.click()}>Upload File</button>
{/* Hidden file input triggered by button */}
<input
ref={fileInputRef}
type="file"
accept="image/*,application/pdf"
style={{ display: "none" }}
onChange={handleFileUpload}
/>
</div>
);
};
export default UploadComponent;
keyon theUploadComponentafter removing a file and that will trigger a re-mount so a new state for that component. Alternatively, but similarly, you can update thekeyon the input so that will be re-mounted.