I have made a small project which takes a csv file and uploads it. it then processes its content to populate mongodb collection
I am getting these two errors:
In VS code console:
API resolved without sending a response for /api/upload, this may result in stalled requests.
and in web app:
Unhandled Runtime Error
Error: Objects are not valid as a React child (found: object with keys {storageErrors}). If you meant to render a collection of children, use an array instead.
Call Stack
throwOnInvalidObjectType
node_modulesreact-domcjsreact-dom.development.js (14887:0)
createChild
node_modulesreact-domcjsreact-dom.development.js (15139:0)
reconcileChildrenArray
node_modulesreact-domcjsreact-dom.development.js (15404:0)
reconcileChildFibers
node_modulesreact-domcjsreact-dom.development.js (15821:0)
reconcileChildren
node_modulesreact-domcjsreact-dom.development.js (19167:0)
updateHostComponent
node_modulesreact-domcjsreact-dom.development.js (19924:0)
beginWork
node_modulesreact-domcjsreact-dom.development.js (21618:0)
HTMLUnknownElement.callCallback
node_modulesreact-domcjsreact-dom.development.js (4164:0)
Object.invokeGuardedCallbackDev
node_modulesreact-domcjsreact-dom.development.js (4213:0)
invokeGuardedCallback
node_modulesreact-domcjsreact-dom.development.js (4277:0)
beginWork$1
node_modulesreact-domcjsreact-dom.development.js (27451:0)
performUnitOfWork
node_modulesreact-domcjsreact-dom.development.js (26557:0)
workLoopSync
node_modulesreact-domcjsreact-dom.development.js (26466:0)
renderRootSync
node_modulesreact-domcjsreact-dom.development.js (26434:0)
performConcurrentWorkOnRoot
node_modulesreact-domcjsreact-dom.development.js (25738:0)
workLoop
node_modulesschedulercjsscheduler.development.js (266:0)
flushWork
node_modulesschedulercjsscheduler.development.js (239:0)
MessagePort.performWorkUntilDeadline
node_modulesschedulercjsscheduler.development.js (533:0)
This is my code for the frontend and API in Nextjs:
Frontend
import { useState } from 'react';
const IndexPage = () => {
const [selectedFile, setSelectedFile] = useState(null);
const [uploading, setUploading] = useState(false);
const [message, setMessage] = useState(null);
const [error, setError] = useState(null);
const handleFileChange = (event) => {
setSelectedFile(event.target.files[0]);
};
const handleFileUpload = async () => {
if (!selectedFile) {
setError('Please select a file');
return;
}
setError(null);
setMessage(null);
setUploading(true);
const formData = new FormData();
formData.append('file', selectedFile);
try {
const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
});
const data = await response.json();
if (response.ok) {
setMessage(data.message);
} else {
setError(data.error);
}
} catch (error) {
setError('Something went wrong');
} finally {
setUploading(false);
}
};
return (
<div>
<h1>File Upload</h1>
<input
name="file"
type="file"
accept=".csv"
onChange={handleFileChange}
/>
<button
onClick={handleFileUpload}
disabled={uploading}
>
{uploading ? 'Uploading...' : 'Upload'}
</button>
{message && <p>{message}</p>}
{error && <p>Error: {error}</p>}
</div>
);
};
export default IndexPage;
This is the Backend
// pages/api/upload.js
import multer from 'multer';
import csv from 'csv-parser';
import fs from 'fs';
import { MongoClient, ObjectId } from 'mongodb';
const upload = multer({
dest: 'uploads/', // Directory to store uploaded files
limits: {
fileSize: 5 * 1024 * 1024, // Limit file size to 5MB
},
fileFilter: (req, file, cb) => {
if (file.mimetype !== 'text/csv') {
cb(new Error('Only CSV files are allowed'));
} else {
cb(null, true);
}
},
});
const saveDistinctValues = async (collectionName, distinctValues) => {
const client = new MongoClient('mongodb://0.0.0.0:27017/testcsv');
try {
await client.connect();
const db = client.db();
const collection = db.collection(collectionName);
await collection.insertMany(distinctValues.map((value) => ({ value })));
} finally {
await client.close();
}
};
const establishRelationships = async () => {
const client = new MongoClient(process.env.MONGODB_URI);
try {
await client.connect();
const db = client.db();
const masterCategoryCollection = db.collection('master_category');
const subCategoryCollection = db.collection('sub_category');
const productGroupCollection = db.collection('product_group');
const productCollection = db.collection('product');
const masterCategories = await masterCategoryCollection.find().toArray();
for (let i = 0; i < masterCategories.length; i++) {
const masterCategory = masterCategories[i];
const subCategory = await subCategoryCollection.findOne({
value: masterCategory.value,
});
const productGroup = await productGroupCollection.findOne({
value: subCategory.value,
});
const products = await productCollection
.find({
subCategoryId: { $exists: false },
masterCategoryId: masterCategory._id,
})
.toArray();
for (let j = 0; j < products.length; j++) {
const product = products[j];
await productCollection.updateOne(
{ _id: product._id },
{
$set: {
subCategoryId: subCategory._id,
productGroupId: productGroup._id,
},
}
);
}
}
} finally {
await client.close();
}
};
const handler = async (req, res) => {
try {
await upload.single('file')(req, res, async (error) => {
if (error instanceof multer.MulterError) {
// Multer error occurred during file upload
res.status(400).json({ error: error.message });
} else if (error) {
// Other errors occurred
res.status(500).json({ error: 'Something went wrong', error });
} else if (!req.file) {
// No file was provided
res.status(400).json({ error: 'No file uploaded' });
} else {
const filePath = req.file.path;
const masterCategories = [];
const subCategories = [];
const productGroups = [];
const products = [];
fs.createReadStream(filePath)
.pipe(csv())
.on('data', (row) => {
const masterCategory = row.master_category.trim();
const subCategory = row.sub_category.trim();
const productGroup = row.product_group.trim();
const product = row.product.trim();
if (masterCategory !== '') {
masterCategories.push({ value: masterCategory });
}
if (subCategory !== '') {
subCategories.push({ value: subCategory });
}
if (productGroup !== '') {
productGroups.push({ value: productGroup });
}
if (product !== '') {
products.push({ value: product });
}
})
.on('end', async () => {
// Save distinct values to collections
await saveDistinctValues('master_category', masterCategories);
await saveDistinctValues('sub_category', subCategories);
await saveDistinctValues('product_group', productGroups);
await saveDistinctValues('product', products);
// Establish relationships between collections
await establishRelationships();
res
.status(200)
.json({ message: 'File uploaded and processed successfully' });
})
.on('error', (error) => {
console.error('Error processing CSV:', error.message);
res.status(500).json({ error: 'Something went wrong' });
});
}
});
} catch (error) {
console.error('Error uploading file:', error.message);
res.status(500).json({ error: 'Something went wrong' });
}
};
export default handler;
I am unable to understand this error as I am new to Next and React. I have looked around and I believe that the problem is with the way I am using the components!
2
Answers
Your React app is erroring because the
error
value you’re trying to display is an object – you can’t put an object directly into the JSX.error
being an object is probably coming from this line, where you’ve used the keyerror
twice, the second instance overriding the first with theError
object.You have this error because you are trying to display your error which is an
Object
.In this scenario you would either check what error you got from the backend and show a error message related. (Where you have
setError(data.error);
)Or
For testing purposes, you can simply display the error as it is, as an object, this way: