I'm facing an issue where the Express API error messages are returning as undefined on the frontend. This is preventing me from displaying proper error messages to alert users.
Interestingly, the error messages seem to appear fine in the developer tools.
My setup involves using Express, Redux, and authentication middleware.
I have been trying to debug this problem but can't seem to figure out where I might have made a mistake. Any insights into why the error messages are undefined?
Error message component (error is undefined so it won't show up)
{error && <Message variant='danger'>{error}</Message>}
errorMiddleware.js
const notFound = (req, res, next) => {
const error = new Error(`Not Found - ${req.originalUrl}`)
res.status(404)
next(error)
}
const errorHandler = (err, req, res, next) => {
const statusCode = res.statusCode === 200 ? 500 : res.statusCode
res.status(statusCode)
res.json({
message: err.message,
stack: process.env.NODE_ENV === 'production' ? null : err.stack
})
}
export { notFound, errorHandler }
Correct error message in dev tools:
https://i.sstatic.net/DIMNs.png
Which matches the login API here:
const authUser = asyncHandler(async (req, res) => {
const { email, password } = req.body
const user = await User.findOne({ email })
if (user && (await user.matchPassword(password))) {
res.json({
_id: user._id,
name: user.name,
email: user.email,
isAdmin: user.isAdmin,
token: generateToken(user._id),
})
} else {
res.status(401)
throw new Error('Invalid email or password')
}
})
User log in action:
export const login = (email, password) => async(dispatch) => {
try {
dispatch({
type: USER_LOGIN_REQUEST
})
const config = {
headers: {
headers: {
'Content-Type': 'application/json'
}
}
}
const { data } = await axios.post('/api/users/login', { email, password }, config)
dispatch({
type: USER_LOGIN_SUCCESS,
payload: data
})
localStorage.setItem('userInfo', JSON.stringify(data))
} catch (error) {
dispatch({
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
})
}
}
server.js
app.use(notFound)
app.use(errorHandler)
User reducer
import { USER_LOGIN_FAIL, USER_LOGIN_SUCCESS, USER_LOGOUT, USER_LOGIN_REQUEST } from '../constants/userConstants'
export const userLoginReducer = (state = { }, action) => {
switch(action.type) {
case USER_LOGIN_REQUEST:
return { loading: true }
case USER_LOGIN_SUCCESS:
return { loading: false, userInfo: action.payload }
case USER_LOGIN_FAIL:
return { loading: false, error: action.payLoad }
case USER_LOGOUT:
return { }
default:
return state
}
}
userRoutes.js
import express from 'express'
const router = express.Router()
import { authUser, getUserProfile, registerUser } from '../controllers/userController.js'
import { protect } from '../middleware/authMiddleware.js'
router.route('/').post(registerUser)
router.post('/login', authUser)
router.route('/profile').get(protect, getUserProfile)
export default router