I have a React / Redux / Node app that is making a request to update a user:
client/src/components/pages/AlignmentPage.tsx
:
const AlignmentPage = () => {
const dispatch = useAppDispatch();
const [alignment, setAlignment] = useState("");
const user: User | null = useAppSelector(
(state: RootState) => state.userData.user
);
const handleSetAlignment = (value: string) => {
setAlignment(value);
displayNewAlignment(value);
if (user) {
console.log("in AlignmentPage.tsx:", { alignment: value });
dispatch(updateUser(user._id, { alignment: value }));
}
};
...
In my Redux action, we are making a call to the PUT endpoint for the user:
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 updatedData = await response.json();
dispatch(updateUserAction(updatedData.user));
} catch (error) {
dispatch(setErrorAction('error updating user!'));
}
}
That controller endpoint looks like this:
exports.updateUser = asyncHandler(async (req: any, res: any, next: any) => {
const { userId } = req.params;
console.log(req.body)
const data = req.body;
const user = await updateUser(userId, data);
res.status(200).json({ user });
});
For some reason, in the controller, I am able to log out the userId param just fine. But the body always returns undefined
and thus the Redux store and Document in Mongo are not being updated. I am able to log the "data" successfully up until the call to const response = await fetch(http://localhost:5000/api/user/${userId}"
in the Redux action. The updatedData
logger returns the original MongoDB object, but without the updated field ("alignment"):
Object { user: {…} }
user: Object { _id: "65d73ae14d1a69c64d6787e6", ipAddress: "::ffff:127.0.0.1", createdAt: "2024-02-22T12:15:29.745Z", … }
__v: 0
_id: "65d73ae14d1a69c64d6787e6"
alignment: ""
createdAt: "2024-02-22T12:15:29.745Z"
ipAddress: "::ffff:127.0.0.1"
It seems like something is preventing the body from being sent to the controller. I'm not sure if this is the way I'm setting up the router or what. I read elsewhere that this may be due to not having bodyParser
middleware installed on the server side, so I implemented this in my server.ts
file, but that hasn't appeared to solve the problem.
(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");
}
})();
api/src/routes/user.ts
:
router.get("/api/user", userController.getUser);
router.put("/api/user/:userId", userController.updateUser);
export { router };
I figured it out.
I needed to pass express.json()
as an argument when calling the user controller endpoint.
api/src/routes/user.ts
:
router.put("/api/user/:userId", express.json(), userController.updateUser);
api/src/controllers/user.ts
:
exports.updateUser = asyncHandler(async (req: any, res: any, next: any) => {
const { userId } = req.params;
const data = req.body;
const user = await updateUser(userId, data);
res.status(200).json({ user });
});
Data is being updated successfully now :)