Hi everyone, for those doing the React Native course in 2024 like me and having issues with the “NETWORKING” chapter, especially when posting listings:
I have updated the code: FEEL FREE TO FORK MY REPO!
https://github.com/CrisRamosLazaro/SparkJoy-backend
Modifications:
1- the package.json has the updated versions of the modules as of Nov 2024
2- The problematic routes > listings is fixed.
The main issue (and I have no idea how it was working for Mosh) is that:
2.1) in the front-end, the location must be stringified before appending it to the FormData,
(which was correctly set as if (location) data.append('location', JSON.stringify(location))
2.2) in the back-end, the Joi schema specifies that the req.body’s location is an object
const schema = Joi.object({
title: Joi.string().required(),
price: Joi.number().required().min(1),
categoryId: Joi.number().required().min(1),
location: Joi.object({ //---------------> here
latitude: Joi.number().required(),
longitude: Joi.number().required(),
}).optional(),
})
2.3) Somehow the command to parse the stringified location back to an object was placed AFTER the validateWith middleware:
router.post("/",
'['
upload.array("images", config.get("maxImageCount")),
validateWith(schema),
//-------> 👆HERE IS WHERE THE VALIDATION CHECKS IF THE LOCATION IS AN OBJECT
validateCategoryId,
imageResize,
],
async (req, res) => {
const listing = {
title: req.body.title,
price: parseFloat(req.body.price),
categoryId: parseInt(req.body.categoryId),
description: req.body.description,
};
listing.images = req.images.map((fileName) => ({ fileName: fileName }));
if (req.body.location) listing.location = JSON.parse(req.body.location);
//-------> 👆 AND HERE IS WHEN THE LOCATION IS PARSED BACK INTO AN OBJECT
// -------> so there will always be an error
if (req.user) listing.userId = req.user.userId;
store.addListing(listing);
res.status(201).send(listing);
})
Now (in the routes >listings.js
) I’ve created the validateLocation
function, where I moved the JSON.parse(req.body.location)
line, and placed it BEFORE the validateWith
middleware in the router.post()
3- The recommended way to perform validation with Joi in newer versions is to call the .validate() method directly on the schema object. This is the approach that aligns with the current Joi API.
So I have modified the middleware > validation.js file from
const Joi = require("joi");
module.exports = schema => (req, res, next) => {
const result = Joi.validate(req.body, schema);
if (result.error)
return res.status(400).send({ error: result.error.details[0].message });
next();
};
to
export default schema => (req, res, next) => {
const { error } = schema.validate(req.body)
if (error) {
return res.status(400).send({ error: error.details[0].message }) }
next()
}
4- I have updated the code to ES6 / modules
5- I have added an .env
file where I’ve transferred the BASE_URL
and PORT
values, and made the corresponding adjustments in the files that required it.
(you’ll need to add that too, ie:
DEV_BASE_URL=http://192.168.0.00:9000/assets BASE_URL=https://moshbucket1.s3.us-east-2.amazonaws.com PORT=9000
)
6- I’ve added the public/assets
folder to my .env
,
You’ll have to copy it from Mosh’s original code
7- I’ve moved the listings
array and the messages
array to a new folder called db
and have imported them in the files that use them.
db/mock-db-listings.js
db/mock-db-messages.js
You’ll have to create the db folder and the files, and copy those arrays from Mosh’s original code (or create your own data)
SIDE NOTE:
I don’t know if it happened to you as well, but I could only get the success Alert if I specified the headers in the frontend repo:
//app>api>listings.js
const saveListing = (listingData) => client.post('/listings', listingData, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
it’s weird, because apisauce is supposed to add this header automatically, or so the course says, but without this declared header, I get an error.