I ran into this issue going through the course as well using the most up-to-date packages as of this writing. Below is the solution step by step for anyone in the future that prefers using updated packages. The version numbers are posted below.
The first change I made was in the front end to listings.js in the API folder. You must specify the content-type in the headers to be “multipart/form-data” for the post request. Apisauce is not defaulting to “multipart/form-data”.
//Before
return client.post(endpoint, data});
//After
return client.post(endpoint, data, {
headers: { "Content-Type": "multipart/form-data" },
});
This update resolved the 500 error from the server; however, the server started sending an error stating that validate is not a valid method of Joi. Updating validation.js in the middleware folder to call the validate method on the schema instead of Joi resolved the issue. See Joi documentation for more details.
//Before
const result = Joi.validate(req.body, schema);
//After
const result = schema.validate(req.body);
After that, it’s necessary to go update Joi usage anywhere in the routes folder to use Joi.object() around the entire object we want to validate. This example is from listings.js.
//Before
const schema = {
title: Joi.string().required(),
description: Joi.string().allow(""),
price: Joi.number().required().min(1),
categoryId: Joi.number().required().min(1),
location: Joi.object({
latitude: Joi.number().required(),
longitude: Joi.number().required(),
}).optional(),
};
//After
const schema = Joi.object({
title: Joi.string().required(),
description: Joi.string().allow(""),
price: Joi.number().required().min(1),
categoryId: Joi.number().required().min(1),
location: Joi.object({
latitude: Joi.number().required(),
longitude: Joi.number().required(),
}).optional(),
});
Lastly, the server started sending a validation error from Joi that location must be an object. It is necessary to use JSON.stringify() in the front end to send the location object to the backend. Joi validation was receiving the object as a string and throwing an error. This is a solution to that issue, but perhaps there is a better solution. This update is in validation.js in the middleware folder as well. Essentially, the code checks if there is a location in the req.body. If there is a location, then it will parse it and pass it as the location object before Joi can validate the data.
//Before & After 1st change to Back End
const result = schema.validate(req.body);
//After
const result = schema.validate(
req.body.location
? { ...req.body, location: JSON.parse(req.body.location) }
: req.body
);
After these changes, the success alert appeared. This solution is using the below package versions in the front end:
"dependencies": {
"@expo/metro-runtime": "3.2.1",
"@react-navigation/bottom-tabs": "^6.5.20",
"@react-navigation/native": "^6.1.17",
"@react-navigation/stack": "^6.3.29",
"apisauce": "^3.0.1",
"expo": "^51.0.2",
"expo-constants": "^16.0.1",
"expo-image-picker": "^15.0.4",
"expo-location": "^17.0.1",
"expo-permissions": "^14.4.0",
"expo-status-bar": "^1.12.1",
"formik": "^2.4.6",
"lottie-react-native": "^6.7.0",
"react": "^18.2.0",
"react-native": "^0.74.1",
"react-native-gesture-handler": "^2.16.2",
"react-native-safe-area-context": "^4.10.1",
"react-native-screens": "^3.31.1",
"yup": "^1.4.0"
},
"devDependencies": {
"@babel/core": "^7.24.5"
},
These versions in the back end:
"engines": {
"node": "21.7.3"
},
"dependencies": {
"body-parser": "^1.20.2",
"compression": "^1.7.4",
"config": "^3.3.11",
"expo-server-sdk": "^3.10.0",
"express": "^4.19.2",
"helmet": "^7.1.0",
"joi": "^17.13.1",
"jsonwebtoken": "^9.0.2",
"multer": "^1.4.5-lts.1",
"sharp": "^0.33.3"
},
"devDependencies": {
"nodemon": "^3.1.0"
}