Young Al Capone
Young Al Capone

Reputation: 399

ReactTs how to execute a get request a lot of times on component

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

Answers (1)

Anees Hikmat Abu Hmiad
Anees Hikmat Abu Hmiad

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);

Another Option:

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]);

Another option

its work base on events nested of api request or Socket or any option...

Upvotes: 1

Related Questions