i'm trying upload multiple file with Dragger of ant design, but when I upload multiple files the onChange event is also called multiple times, it causes duplicate files
const handleChange = ({ fileList }) => {
console.log(fileList);
setFileList(fileList.filter(file => file.status !== "error"));
var notUploadYet = fileList.reduce((accumulator, file) => {
if (!fileUploaded.find(x => x.name === file.name)) {
accumulator.push(file);
}
return accumulator;
}, [])
const handleUpload = async () => {
try {
for await (const file of notUploadYet) {
const typeMedia = file.type.split('/')[0]
var nameOnCloud = typeMedia === "video" ? `videos/${file.name + v4()}` : `images/${file.name + v4()}`
const storageRef = ref(storage, nameOnCloud);
await uploadBytes(storageRef, file.originFileObj)
console.log('upload success')
try {
const link = await getDownloadURL(storageRef)
setFileUploaded([...fileUploaded,
{
name: file.name,
link: link,
nameOnCloud: nameOnCloud,
type: typeMedia
}
])
} catch (error) {
console.log(error)
}
}
} catch (error) {
console.log(error)
}
}
handleUpload()
}
<Dragger
listType="picture-card"
fileList={fileList}
beforeUpload={beforeUpload}
onPreview={handlePreview}
onChange={handleChange}
onRemove={handleOnRemove}
multiple={true}
>
<AiOutlineUpload style={{ 'fontSize': 30 }} />
<div className="uploadText">
<p>Kéo và thả ở đây hoặc click để chọn</p>
</div>
</Dragger>
I want the onChange event to be called only once when I upload multiple files
Related
I want to loop through multiple images in a map and scale them down. My input tag is multiple but I don't get a conventional array as shown in the picture. Why is that, or what should I change?
const articelImg = (e) => {
setFiles([...files, e.target.files]);
};
useEffect(() => {
if (file.length) {
file.map(async (fi, idx) => {
try {
const image = await resizeFile(fi[idx]);
setResizeFiles([...resizeFiles, image]);
console.log("IMAGE: " + idx + " ----" + image);
} catch (error) {
console.log(error);
}
});
}
}, [file]);
And in my useEffect method, when I display the array, only ONE object is displayed
useEffect(() => {
const showRez = () => {
if (resizeFiles.length) {
console.log(resizeFiles); // ONLY ONE OBJECT
}
};
showRez();
}, [resizeFiles]);
<input hidden accept="image/*" type="file" multiple onChange={(e) => articelImg(e)} />
I have the following:
<input style={{display: 'none'}} accept="image/*,.pdf,.docx,.xlsx,.gpx,text/xml,text/gpsxml,application/gpsxml" id="icon-button-file" type="file" onChange={event => onImageChanges(event)} />
This is part of an array, and what I am trying to do is pass the index to onImageChanges:
{data && data.Itinerary && data.Itinerary.length > 0 && data.Itinerary?.map((aaa, index) => {
const onImageChanges = (e) => {
console.log('HERE');
var file = e.target.files[0];
if (file === null) {
console.error(`not an image, the image file is a`)
}
const uploadTask = storage.ref(`${user1}/${aaa.Date}/${file.name}`).put(file)
uploadTask.on('state_changed',
(snapShot) => {
}, (err) => {
console.log(err)
}, () => {
storage.ref(`${user1}/${aaa.Date}`).child(file.name).getDownloadURL()
.then(fireBaseUrl => {
data.Itinerary[index].Document.push({ url: fireBaseUrl, name: file.name })
setItem(data)
alert("File Upload Successfully")
})
})
}
}
I need it for this line:
data.Itinerary[index].Document.push({ url: fireBaseUrl, name: file.name })
I think the title is self-explanatory. What am I doing wrong below? What I want to achieve is getting the text out of a photo, right after the user selects a photo.
The error I get is:
createWorker.js:173 Uncaught Error: RuntimeError: null function or function signature mismatch
What am I doing wrong?
const { createWorker } = require("tesseract.js");
const [file,setFile] = useState();
const worker = createWorker({
logger: (m) => console.log(m),
});
const doOCR = async (image) => {
await worker.load();
await worker.loadLanguage("eng");
await worker.initialize("eng");
const {
data: { text },
} = await worker.recognize(image);
// } = await worker.recognize('https://tesseract.projectnaptha.com/img/eng_bw.png');
console.log(text);
setOcr(text);
};
const [ocr, setOcr] = useState("Recognizing...");
useEffect(() => {
file ? doOCR(file) : console.log('no file selected yet!');
}, [file]);
const getFile = (e) => {
console.log("Upload event:", e);
if (e) {
if (Array.isArray(e)) setFile(e[0]);
setFile(e)
}
}
....
<p>{ocr}</p> /* this only displays "Recognizing..." */
<Form.Item
name="uploadedPhoto"
label="Upload your photo scan"
getValueFromEvent={getFile}
// rules={[{ required: true }]}>
<Input type="file"
// onChange={onImageUpload}
/>
</Form.Item>
Solved it by doing it like this instead of the above (I applied the function to the onChange of the Input itself, not the Form.Item element)
const handleFileSelected = (e) => {
const files = Array.from(e.target.files);
setFile(files[0]);
};
<Input type="file" onChange={handleFileSelected} />
const csvLinkRef = useRef(null)
const exportFile = () => {
let data= {data:'info'}
//Async Action
dispatch(
getFileData(data,
()=>{
csvLinkRef.current.link.click()
}
))
}
<Button onClick={exportFile}> //run exportFile on click
<CSVLink
filename={'file.csv'}
data={someData}
ref={csvLinkRef}//set ref here
>
Export
</CSVLink>
</Button>
//Async API call using redux thunk
export const getFileData = (data,cb) => async dispatch => {
try{
const res = await callApi('ever.php',data,'POST')// make api call
if(res.status==="00"){
dispatch({
type:GET_ALL_DATA,
data: res.data,
})
}
}catch(error){
console.log(error)
}finally{
cb()
}
}
My issue is csvLinkRef.current.link.click() fires non-stop after the API call. How can I make it fire just once? Is there a way I can 'unset' the ref? Please help.(I'm using react-csv library).
The getFileData action API call is successful and the data is in redux state.
if csvLinkRef.current.link.click fired only once, everything would be fine
I had the same problem. Now it is solved. You can try it...
function CsvExample({ manufacturerList }: IdLinkCreateProps) {
const httpRequests = new HttpRequests()
const csvInstance = useRef<any | null>(null);
const [alertOpt, setAlertOpt] = useState({ isOpen: false, message: '', variant: '' })
const [manufacturer, setManufacturer] = useState<IManufacturerItem | null>(null)
const [quantity, setQuantity] = useState<number>(0)
const [idList, setIdList] = useState<{ idList: string }[]>([])
const header = [{ label: "Digital-Links", key: "idLink" }];
const createIdLink = async () => {
let data: IIdLinkCreate = { manufacturer: manufacturer!, quantity: quantity! }
try {
const result = await httpRequests.idLinkCreate(data)
setSuccessOptions(result)
} catch (error) {
console.log('error on getting trusted manufacturer list: ', error);
}
return
}
const setSuccessOptions = (result: IBackendResult) => {
if (result.success) {
setIdList(result.data);
} else {
setAlertOpt({ isOpen: true, message: 'FAILED', variant: 'danger' })
console.log('error on updating data: ', result.error);
}
}
useEffect(() => {
if (idList && idList.length > 0 && csvInstance?.current?.link) {
csvInstance.current.link.click();
}
}, [idList]);
return (
<div className='id_link_wrapper'>
<AppHeader />
<Alert className="alert_error" variant={alertOpt.variant} show={alertOpt.isOpen} >
{alertOpt.message}
</Alert>
<IdLinkTitlePart />
<IdLinkInputPart
manufacturerList={manufacturerList}
setManufacturer={setManufacturer}
setQuantity={setQuantity}
quantity={quantity}
/>
<Button
onClick={createIdLink}
className='button_element'> CSV EXPORTIEREN
</Button>
<CSVLink
asyncOnClick={true}
headers={header}
data={idList!}
filename="bsedata.csv"
data-interception='off'
ref={csvInstance}
/>
</div>
)
}
export default CsvExample
const MyUploader = () => {
const getUploadParams = ({ meta,url }) => { // specify upload params and url for your files
console.log("uploadParams",meta,url)
return { url: '/v1/file_uploads/' }
}
const handleChangeStatus = ({ meta, file }, status) => { // called every time a file's `status` changes
console.log("handleStatus",status, meta, file)
}
const handleSubmit = (files, allFiles) => { // receives array of files that are done uploading when submit button is clicked
console.log(files.map(f => f.meta))
allFiles.forEach(f => f.remove())
}
return (
<Dropzone
getUploadParams={getUploadParams}
onChangeStatus={handleChangeStatus}
onSubmit={handleSubmit}
accept="image/*"
/>
)
}
<MyUploader />
I'm able to save the uploaded file in the Database, when file is saved i am rendering some information
render json: {status: "Success", blob: blob, url: URL }
How can i console log this data which i am rendering in the React ??
The link of the package is : https://github.com/fortana-co/react-dropzone-uploader
I have solved the problem by passing xhr as a parameter to handleChangeStatus function.
const MyUploader = () => {
const getUploadParams = ({ meta }) => { // specify upload params and url for your files
return { url: '/v1/file_uploads/' }
}
const handleChangeStatus = ({ meta, file,xhr }, status) => { // called every time a file's `status` changes
console.log("handleStatus",status, meta, file)
if(status == "done") {
var json = JSON.parse(xhr.response)
var arr_blob_ids = state.documents_blob_ids.slice()
console.log("id added",json.blob.id)
if (json.blob.id){
arr_blob_ids.push(json.blob.id)
setState({...state,documents_blob_ids: arr_blob_ids})
}
}
else if(status == "removed") {
var json = JSON.parse(xhr.response)
var arr_blob_ids = state.documents_blob_ids.slice()
console.log("id removed",json.blob.id)
if (json.blob.id){
arr_blob_ids = arr_blob_ids.filter( v => v!= json.blob.id)
setState({...state,documents_blob_ids: arr_blob_ids})
}
}
}
const handleSubmit = (files, allFiles) => { // receives array of files that are done uploading when submit button is clicked
console.log(files.map(f => f.meta))
allFiles.forEach(f => f.remove())
}
return (
<Dropzone
getUploadParams={getUploadParams}
onChangeStatus={handleChangeStatus}
onSubmit={handleSubmit}
accept="image/*"
submitButtonContent = {null}
SubmitButtonComponent = {null}
/>
)
}