简体   繁体   中英

React hooks, not re-rendering

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,
};

您的 useEffect 钩子需要将文件列表变量作为更新反映的依赖项。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM