I have a React / Node / Express app where I am trying to update a user.
The Redux action that should be handling the request looks like this:
export const updateUser = (userId: string, data: any) => async (dispatch: any) => {
try {
dispatch(setLoadingAction(true));
const response = await fetch(`http://localhost:5000/api/user/${userId}`, {
method: 'PUT',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
const updatedUser = await response.json();
dispatch(updateUserAction(updatedUser.user));
} catch (error) {
dispatch(setErrorAction('error updating user!'));
}
}
The actual controller endpoint that I am hitting:
exports.updateUser = asyncHandler(async (req: any, res: any, next: any) => {
const { userId } = req.params;
console.log(req.body)
const data = req.body;
console.log('in controllers/user.ts, userId:', userId);
console.log('in controllers/user.ts, data:', JSON.stringify(data));
const user = await updateUser(userId, data);
res.status(200).json({ user });
});
I have both GET and PUT routes defined for the user:
import express, { Request, Response } from "express";
const router = express.Router();
const userController = require("../controllers/user");
// GET /user/:ipAddress
// router.post("/", userController.createUser);
router.get("/api/user", userController.getUser);
router.put("/api/user/:userId", userController.updateUser);
export { router };
In my server.ts file I am using bodyParser (although I understand that Express should be handling this out of the box, so bodyParser might not be needed.
(async () => {
const port = env.PORT;
app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/api/user', userRouter);
try {
app.listen(port, () => {
db.on("error", console.error.bind(console, "connection error:"));
db.on("connected", function () {
console.log("Connected to MongoDB");
});
console.log(`Server started at http://localhost:${port}`);
});
} catch (err) {
const error = new Error("Request failed");
console.log(err);
throw error;
} finally {
console.log("Server started");
}
})();
For some reason, regardless of whether I use cURL, Postman, or try to hit the endpoint via the app itself, the body is null every time, although params seem to be getting passed successfully, and the response I get is always a 200.
Request (using cURL):
`curl -X PUT -H "Content-Type: application/json" -d '{"alignment":"pro"}' http://localhost:5000/api/user/65d73ae14d1a69c64d6787e6
Response:
{"user":{"_id":"65d73ae14d1a69c64d6787e6","ipAddress":"::ffff:127.0.0.1","alignment":"","createdAt":"2024-02-22T12:15:29.745Z","__v":0}}%
I would expect the alignment value on the user to have been set. When I put loggers inside of the updateUser action or the controller endpoint itself, the request data is always undefined.
in controllers/user.ts, userId: 65d73ae14d1a69c64d6787e6
in controllers/user.ts, data: undefined
I figured it out.
I needed to pass
express.json()as an argument when calling the user controller endpoint.api/src/routes/user.ts:api/src/controllers/user.ts:Data is being updated successfully now :)