A use case is:
- user drops a file
- Take a file and read with
exceljs
- grab values from a column and keep it inside an array
ids
- set a state variable
onDropIds
with the contents ofids
. I got steps1
-3
working. I can't get4
to work.
See: State always prints empty, even though the set contains values. See code lines 41-43.
import React, { useState, useCallback } from "react";
import { useDropzone } from "react-dropzone";
import Excel from "exceljs";
export default function Test(props) {
// Local state
const [onDropIds, setOnDropIds] = useState(new Set());
// Callback fires as soon as the file is dropped
const onDrop = useCallback((acceptedFiles) => {
const file = acceptedFiles[0];
const reader = new FileReader(); // reads the file using the `FileReader` API
reader.onabort = () =>
console.warn(`Reading of file ${file.path} was aborted.`);
reader.onerror = () =>
console.error(`Reading of file ${file.path} has failed.`);
reader.onloadend = (e) => {
const bufferArray = reader.result;
// temporarily hold a set of values
const ids = new Set();
const workbook = new Excel.Workbook();
workbook.xlsx
.load(bufferArray)
.then((sheet) => {
workbook.worksheets[0].eachRow({ includeEmpty: true }, (row) => {
const colValue1 = (row.values[1] || "").trim().toUpperCase();
if (colValue1 && colValue1 !== "HEADERNAME") {
ids.add(colValue1);
}
});
})
.then(() => {
// set it to the state
setOnDropIds(ids);
// debug: print results
console.log(onDropIds);
console.log("---");
console.log(ids);
});
};
reader.readAsArrayBuffer(file);
}, []);
// Initialize the dropzone hook
const { getRootProps, getInputProps, open, acceptedFiles } = useDropzone({
noClick: true,
noKeyboard: true,
multiple: false,
onDrop,
});
return (
<div>
<div
{...getRootProps()}
style={
acceptedFiles && acceptedFiles.length
? {
textAlign: "center",
border: "1px solid #198562",
marginTop: "0.5em",
backgroundColor: "#d9fff3",
}
: {
textAlign: "center",
border: "1px dashed #000",
marginTop: "0.5em",
}
}
>
<input {...getInputProps()} />
<button
style={{ marginTop: "0.5em" }}
color={acceptedFiles && acceptedFiles.length ? "#00ff00" : "#ff0000"}
onClick={open}
>
Browse
</button>
{acceptedFiles && acceptedFiles.length ? (
<span>
{acceptedFiles[0].path}{" "}
<i className="fas fa-check-circle" style={{ color: "#75B436" }}></i>
</span>
) : (
"Drag 'n' drop a file here..."
)}
</div>
</div>
);
}