Reputation: 399
I'm learning ReactTs and I'm coding a simple two components app to Upload a file and with another request obtain upload progress, but I can't receive the progress data from request. I think useEffect never execute the axios get request. How Can execute a lot of times the get request to obtain 0-100 progress? Thanks for your help!
Principal Component:
import axios from 'axios';
import React, { Fragment, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { transactionFileAction, uploadFileAction } from '../../actions/uploadFileAction';
import { RootStore } from '../../store';
import ProgressBar from '../progressBar/ProgressBar';
const UploadFile: React.FC = () => {
const dispatch = useDispatch();
const uploadFileStore = useSelector((state: RootStore) => state.uploadFile);
const [file, setFile] = useState<FormData>();
const [uploadProgress, setUploadProgress] = useState<number | undefined>(0);
const [uploadStatus, setUploadStatus] = useState<boolean>(false);
useEffect(() => {
if (uploadStatus) setUploadStatus(false);
}, [uploadStatus, uploadFileStore]);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files.length > 0) {
const formData = new FormData();
formData.append("file", e.target.files[0]);
setFile(formData);
}
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
dispatch(uploadFileAction(file));
setUploadStatus(true);
};
return (
<Fragment>
<form onSubmit={(e) => handleSubmit(e)}>
<label>Notes</label>
<input
type="file"
name="file"
accept=".pdf,.doc,.docx,.xls,.xlsx"
onChange={(e) => handleChange(e)}
/>
<button type="submit">Agregar</button>
{uploadFileStore.UploadFileResponse?.message ? (
<p>{uploadFileStore.UploadFileResponse?.message}</p>
) : null}
</form>
{uploadFileStore.UploadFileResponse?.transactionId ? (
<ProgressBar
transactionId={uploadFileStore.UploadFileResponse?.transactionId}
/>
) : null}
</Fragment>
);
};
export default UploadFile;
Upload Progress Component:
import axios from 'axios';
import React, { useEffect, useState } from 'react';
interface Props {
transactionId: string | undefined;
}
const ProgressBar: React.FC<Props> = ({ transactionId }) => {
const [uploadProgress, setUploadProgress] = useState<number | undefined>(0);
console.log("entra");
useEffect(() => {
axios
.get(`http://localhost:3000/file_parser/${transactionId}`)
.then((response) => {
setUploadProgress(response.data.progress);
});
}, [transactionId, uploadProgress]);
return (
<div>
<p>{transactionId}</p>
<p>Progreso: {uploadProgress && uploadProgress}</p>
</div>
);
};
export default ProgressBar;
Upvotes: 1
Views: 97
Reputation: 3560
Since you need to make a request and this will not trigger re-render else one time since transaction will only call one time, then you can do that via use time interval for request to progress every 1 second for example...
ex: let us has an useInterval custom hook:
import React, { useEffect, useRef } from 'react';
const useInterval = (callback, delay) => {
const savedCallback = useRef();
// Remember the latest callback.
savedCallback.current = callback;
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
export default useInterval;
Then in my component we can call it:
useInterval(() => {
if(!transactionId) return;
axios
.get(`http://localhost:3000/file_parser/${transactionId}`)
.then((response) => {
setUploadProgress(response.data.progress);
});
}, 1000);
Base on result from api, we keep check if the progress response is 100 or not, if not then trigger it again... for example:
const [forceUpdate, setForceUpdate] = useState(null);
useEffect(() => {
axios
.get(`http://localhost:3000/file_parser/${transactionId}`)
.then((response) => {
setUploadProgress(response.data.progress);
if(response.data.progress !== 100){
setForceUpdate(new Date());
}
});
}, [transactionId, forceUpdate]);
its work base on events nested of api request or Socket or any option...
Upvotes: 1