-1

I am new to React and hooks and i can't figure out why i can't get the list of files in my app to refresh after i click convert. It will only show the correct file if i refresh the page.

Here is the React part. I upload a file in csv format, then once it is uploaded, i click the convert button which will extract the info needed and then written to an excel file.

import React, { useState, useEffect } from "react";
import UploadService from "../services/FileUploadService";

const UploadFiles = () => {
  const [selectedFiles, setSelectedFiles] = useState(undefined);
  const [currentFile, setCurrentFile] = useState(undefined);
  const [progress, setProgress] = useState(0);
  const [message, setMessage] = useState("");
  const [fileInfos, setFileInfos] = useState([]);

  useEffect(() => {
    UploadService.getFiles().then((response) => {
      setFileInfos(response.data);
    });
    UploadService.getFinalFiles().then((response) => {
      setFileInfos(response.data);
    });
  }, []);

  const selectFile = (event) => {
    setSelectedFiles(event.target.files);
  };

  const upload = () => {
    let currentFile = selectedFiles[0];

    setProgress(0);
    setCurrentFile(currentFile);

    UploadService.upload(currentFile, (event) => {
      setProgress(Math.round((100 * event.loaded) / event.total));
    })
      .then((response) => {
        setMessage(response.data.message);
        return UploadService.getFiles();
      })
      .then((files) => {
        setFileInfos(files.data);
      })
      .catch(() => {
        setProgress(0);
        setMessage("Could not upload the file!");
        setCurrentFile(undefined);
      });

    setSelectedFiles(undefined);
  };

  const convert = () => {
    // let currentFile = selectedFiles[0];

    UploadService.convert(currentFile, (event) => {
      // setProgress(Math.round((100 * event.loaded) / event.total));
      console.log(event);
    })
      .then((response) => {
        setProgress(0);
        setMessage(response.data.message);
        return UploadService.getFinalFiles();
      })
      .then((files) => {
        console.log(files);
        setFileInfos(files.data);
      })
      .catch(() => {
        setProgress(0);
        setMessage("Could not convert the file!");
        setCurrentFile(undefined);
      });

    setSelectedFiles(undefined);
  };

  return (
    <div>
      {currentFile && (
        <div className="progress">
          <div
            className="progress-bar progress-bar-info progress-bar-striped"
            role="progressbar"
            aria-valuenow={progress}
            aria-valuemin="0"
            aria-valuemax="100"
            style={{ width: progress + "%" }}
          >
            {progress}%
          </div>
        </div>
      )}

      <label className="btn btn-default">
        <input type="file" onChange={selectFile} />
      </label>

      <button
        className="btn btn-success"
        disabled={!selectedFiles}
        onClick={upload}
      >
        Upload
      </button>

      <button
        className="btn btn-info"
        disabled={!message}
        onClick={convert}
        style={{ marginLeft: "5px" }}
      >
        convert
      </button>

      <div className="alert alert-light" role="alert">
        {message}
      </div>

      <div className="card">
        <div className="card-header">List of Files</div>
        <ul className="list-group list-group-flush">
          {fileInfos &&
            fileInfos.map((file, index) => (
              <li className="list-group-item" key={index}>
                <a href={file.url}>{file.name}</a>
              </li>
            ))}
        </ul>
      </div>
    </div>
  );
};

export default UploadFiles;

Here is the file controller, the convert part will take the csv file, extract the info and write it to an excel file. After that it will delete the csv file and i want the list to show the correct final result file after clicking the convert button without refreshing the page.

const uploadFile = require("../middleware/upload");
const fs = require("fs");
const baseUrl = "http://localhost:8080/files/";
// Modules imports
const ExcelJS = require("exceljs");
const path =
  "C:\\vsprojects\\csv-upload\\oppo-csat\\api\\resources\\static\\assets\\uploads";
const csv = require("@fast-csv/parse");
const moment = require("moment");

const upload = async (req, res) => {
  try {
    await uploadFile(req, res);

    if (req.file == undefined) {
      return res.status(400).send({ message: "Please upload a file!" });
    }

    res.status(200).send({
      message: "Uploaded the file successfully: " + req.file.originalname,
    });
  } catch (err) {
    console.log(err);

    if (err.code == "LIMIT_FILE_SIZE") {
      return res.status(500).send({
        message: "File size cannot be larger than 2MB!",
      });
    }

    res.status(500).send({
      message: `Could not upload the file: ${req.file.originalname}. ${err}`,
    });
  }
};

const convert = async (req, res) => {
  const directoryPath = __basedir + "/resources/static/assets/uploads/";
  const finalPath = __basedir + "/resources/static/assets/downloads/";

  try {
    const date = moment("25/10/2020", "DD/MM/YYYY");
    const cases = [];

    await fs.readdirSync(directoryPath).forEach((file) => {
      fs.createReadStream(`${directoryPath}/${file}`)
        .pipe(csv.parse({ headers: true, delimiter: ";" }))
        .on("error", (error) => console.error(error))
        .on("data", async (row) => {
          let fcr = "";
          if (
            row["Satisfaction Demande"] === "Da" ||
            row["Satisfaction Demande"] === "Ja" ||
            row["Satisfaction Demande"] === "Tak" ||
            row["Satisfaction Demande"] === "Oui" ||
            row["Satisfaction Demande"] === "Yes"
          ) {
            fcr = "Yes";
          }
          if (
            row["Satisfaction Demande"] === "Nu" ||
            row["Satisfaction Demande"] === "No" ||
            row["Satisfaction Demande"] === "Non" ||
            row["Satisfaction Demande"] === "Nie" ||
            row["Satisfaction Demande"] === "Nee" ||
            row["Satisfaction Demande"] === "Nein"
          ) {
            fcr = "No";
          }
          if (
            row["[CASE_ORIGINE]"] === "Email entrant" &&
            row["[REGION2]"] !== "FR" &&
            row["[REGION2]"] !== "" &&
            row["Satisfaction note"] !== "" &&
            row.date_reponse !== "" &&
            row["[CALLERNO_EMAIL_SOCIAL]"] !== "" &&
            row["[CALLERNO_EMAIL_SOCIAL]"].includes("-") &&
            row["Satisfaction note"] !== "5" &&
            moment(row.date_reponse.slice(0, 10), "DD/MM/YYYY") > date
          ) {
            await cases.push({
              "Case ID": row["[CALLERNO_EMAIL_SOCIAL]"],
              "Email address": row["[EMAIL]"],
              Agent: row["[AGENT]"],
              Region: row["[REGION2]"],
              "CSAT note": row["Satisfaction note"],
              FCR: fcr,
            });

            let rowNum = 2;
            const workbook = new ExcelJS.Workbook();
            const worksheet = workbook.addWorksheet("csat");
            // const file = await workbook.xlsx.readFile("test.xlsx");
            // const worksheet = await file.getWorksheet(1);
            cases.forEach((item) => {
              worksheet.getRow(rowNum).getCell(1).value = item["Case ID"];
              worksheet.getRow(rowNum).getCell(2).value = item["Email address"];
              worksheet.getRow(rowNum).getCell(3).value = item.Agent;
              worksheet.getRow(rowNum).getCell(4).value = item.Region;
              worksheet.getRow(rowNum).getCell(5).value = parseInt(
                item["CSAT note"],
                10
              );
              worksheet.getRow(rowNum).getCell(6).value = item.FCR;
              worksheet.getRow(rowNum).commit();
              rowNum += 1;
            });
            await workbook.xlsx.writeFile(`${finalPath}/results.xlsx`);
          }
        })
        .on("end", (rowCount) => {
          fs.unlinkSync(`${directoryPath}/${file}`);
          console.log(`Parsed ${rowCount} rows`);
        });
    });
    res.status(200).send("done");
  } catch (err) {
    console.log(err);

    res.status(500).send({
      message: `Could not convert the file: ${err}`,
    });
  }
};

const getListFiles = (req, res) => {
  const directoryPath = __basedir + "/resources/static/assets/uploads/";

  fs.readdir(directoryPath, function (err, files) {
    if (err) {
      res.status(500).send({
        message: "Unable to scan files!",
      });
    }

    let fileInfos = [];

    files.forEach((file) => {
      fileInfos.push({
        name: file,
        url: baseUrl + file,
      });
    });

    res.status(200).send(fileInfos);
  });
};
const getFinalFiles = (req, res) => {
  const directoryPath = __basedir + "/resources/static/assets/downloads/";

  fs.readdir(directoryPath, function (err, files) {
    if (err) {
      res.status(500).send({
        message: "Unable to scan files!",
      });
    }

    let fileInfos = [];

    files.forEach((file) => {
      fileInfos.push({
        name: file,
        url: baseUrl + file,
      });
    });

    res.status(200).send(fileInfos);
  });
};

const download = (req, res) => {
  const fileName = req.params.name;
  const directoryPath = __basedir + "/resources/static/assets/uploads/";

  res.download(directoryPath + fileName, fileName, (err) => {
    if (err) {
      res.status(500).send({
        message: "Could not download the file. " + err,
      });
    }
  });
};

module.exports = {
  upload,
  convert,
  getListFiles,
  getFinalFiles,
  download,
};
Adrian Sultu
  • 330
  • 5
  • 16

1 Answers1

-1

Your useEffect hook needs to have the file list variable as a dependency for the update to reflect.