0
votes

I was requesting for some help with the below error which is occurring in my React js Frontend in my Login Form after Submitting required details inside the form.

Unhandled Rejection (TypeError): Cannot read property 'data' of undefined

This is a screenshot Chrome of the error displayed on Chrome and the Chrome console image

It occured when I was trying to login after clicking the Submit button of my Login form but on my backend since am working on a MERN App it actually submits the data correctly and verifies it and I get a 200 Success message, the screenshot to my VS Code Console. image

What I was thinking the error mainly was occuring on my React Frontend and my backened was running smoothly, I tried looking about the error on the Internet and could not get the specific fix for it but it had to do with a try and catch to fix it but did not workout successfully on my end.

The code below is the specific code on my Login.js which is bringing the error.

  241 |           password1: '',
  242 |           textChange: 'Sign In'
  243 |         });
> 244 |         toast.error(err.response.data.errors); //This is the line where React is complaining of the error
      | ^  245 |       });
  246 | } else {
  247 |   toast.error('Please fill all fields');

The Full Code for my Login.js file is as below;

import React, { useState } from 'react'
import authSvg from '../assets/login.svg'
import { ToastContainer, toast } from 'react-toastify';
import { authenticate, isAuth } from '../helpers/auth';
import axios from 'axios';
// import { Redirect } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';


const Login = ({ history }) => {
    const [formData, setFormData] = useState({
        email: '',
        password1: '',
        textChange: 'Sign In'
    })

    const {email, password1, textChange } = formData
    // Handle change inputs
    const handleChange = text => e => {
        // console.log(username, email, phone, firstName, lastName, password)
        setFormData({...formData, [text]: e.target.value})
    }

    // Submit data to backend
    const handleSubmit = e => {
        console.log(process.env.REACT_APP_API_URL);
        e.preventDefault()
        if (email && password1){
            setFormData({ ...formData, textChange: 'Submitting' });
            axios.post(`${process.env.REACT_APP_API_URL}/login`, {
                email,
                password: password1
            }).then(res => {
                authenticate(res, () => {
                    setFormData({
                        ...formData,
                        email: '',
                        password1: '',
                        textChange: 'Submitted'
                    })
                    console.log(res.data)
                })
                  // if authenticate but not admin redirect to / private
                  // if admin redirect to /admin
              isAuth() && isAuth().role === 'admin'
                  ?history.push('/')
                  :history.push('/register'); //Here for now am testing the routing with the available routes I have at the moment
              toast.success(`Hey ${res.data.user.username}, Welcome back!`);
                  toast.success(`Hey ${res.data.user.username}, Welcome back!`);
                })
                .catch(err => {
                  setFormData({
                    ...formData,
                    email: '',
                    password1: '',
                    textChange: 'Sign In'
                  });
                  toast.error(err.response.data.errors); //This is the line where I get the React **undefined** Error
                });
          } else {
            toast.error('Please fill all fields');
          }
        };

    const navigate = useNavigate();

    return (
        <div className='min-h-screen bg-gray-100 text-gray-900 flex justify-center'>
          {/* {isAuth() ? <Redirect to='/' /> : null} */}
        {isAuth() ? <navigate to='/' /> : null}
        <ToastContainer />
        <div className='max-w-screen-xl m-0 sm:m-20 bg-white shadow sm:rounded-lg flex justify-center flex-1'>
          <div className='lg:w-1/2 xl:w-5/12 p-6 sm:p-12'>
            <div className='mt-12 flex flex-col items-center'>
              <h1 className='text-2xl xl:text-3xl font-extrabold'>
                Sign In for Ntuma
              </h1>
  
              <form
                className='w-full flex-1 mt-8 text-indigo-500'
                onSubmit={handleSubmit}
              >
                <div className='mx-auto max-w-xs relative '>
                  <input
                    className='w-full px-8 py-4 rounded-lg font-medium bg-gray-100 border border-gray-200 placeholder-gray-500 text-sm focus:outline-none focus:border-gray-400 focus:bg-white mt-5'
                    type='email'
                    placeholder='Email'
                    onChange={handleChange('email')}
                    value={email}
                  />
                  <input
                    className='w-full px-8 py-4 rounded-lg font-medium bg-gray-100 border border-gray-200 placeholder-gray-500 text-sm focus:outline-none focus:border-gray-400 focus:bg-white mt-5'
                    type='password'
                    placeholder='Password'
                    onChange={handleChange('password1')}
                    value={password1}
                  />
                  <button
                    type='submit'
                    className='mt-5 tracking-wide font-semibold bg-indigo-500 text-gray-100 w-full py-4 rounded-lg hover:bg-indigo-700 transition-all duration-300 ease-in-out flex items-center justify-center focus:shadow-outline focus:outline-none'
                  >
                    <i className='fas fa-user-plus fa 1x w-6  -ml-2' />
                    <span className='ml-3'>{textChange}</span>
                  </button>
                  <a
                    href='/users/password/forget'
                    className='no-underline hover:underline text-indigo-500 text-md text-right absolute right-0  mt-2'
                >
                  Forget password?
                </a>
                </div>
                <div className='my-12 border-b text-center'>
                  <div className='leading-none px-2 inline-block text-sm text-gray-600 tracking-wide font-medium bg-white transform translate-y-1/2'>
                    Or Sign Up
                  </div>
                </div>
                <div className='flex flex-col items-center'>
                  <a
                    className='w-full max-w-xs font-bold shadow-sm rounded-lg py-3
             bg-indigo-100 text-gray-800 flex items-center justify-center transition-all duration-300 ease-in-out focus:outline-none hover:shadow focus:shadow-sm focus:shadow-outline mt-5'
                    href='/register'
                    target='_self'
                  >
                    <i className='fas fa-sign-in-alt fa 1x w-6  -ml-2 text-indigo-500' />
                    <span className='ml-4'>Log In</span>
                  </a>
                </div>
              </form>
            </div>
          </div>
          <div className='flex-1 bg-indigo-100 text-center hidden lg:flex'>
            <div
              className='m-12 xl:m-16 w-full bg-contain bg-center bg-no-repeat'
              style={{ backgroundImage: `url(${authSvg})` }}
            ></div>
          </div>
        </div>
        ;
      </div>
    );
};

export default Login

These are the controllers on my backend I was using for my Login.js frontend form called loginController but for the Backend seems to be alright since I got a 200 Success message on the VS Code console as shown in the images above

exports.loginController = (req, res) => {
  const { email, password } = req.body
  const errors = validationResult(req)

  // Validation to req.body we will create custom validation in seconds
  if (!errors.isEmpty()) {
    const firstError = errors.array().map((error) => error.msg)[0];
    return res.status(422).json({
      errors: firstError,
    });
  } else {
    // Check if user exist
    RegistersignUp.findOne({
      email
    }).exec((err, user) => {
      if (err || !user) {
        return res.status(400).json({
          errors: 'User with that email does not exist. Please Signup'
        });
      }
    
      // Authenticate
      if (!user.authenticate(password)) {
        return res.status(400).json({
          errors: 'Email and password do not match'
        })
      }

      // Generate Token
      const token = jwt.sign(
        {
          _id: user._id
        }, process.env.JWT_SECRET,
        {
          expiresIn: '7d' // Token valid in 7 day you can set remember in front and set it for 30 days
        }
      )
      const {
        _id,
        username,
        email,
        role,
      } = user
      return res.json({
        token,
        user: {
          _id,
          username,
          email,
          role
        }
      })
    })
  }
}

After adding console.log(err) to my code this is the Output that occured in the Chrome Console. The Error message displayed read

TypeError Cannot read property 'push' of undefined

And also here is a Screenshot below to the Chrome console.log output Screenshot

3
Use console.log(err) so you can see what it returns.Valentin
I added the console.log(err) right ontop of the toast and this is the error I got screenshot link imgur.com/undefined error message after consoling is "TypeError: Cannot read property 'push' of undefined"AJ PHIL
Good morning Sorrry seems this screenshot had an error think it was network but I had still uploaded the picture this is a resent screenshot for some guidance please imgur.com/PxfIN2FAJ PHIL

3 Answers

0
votes

At first, you need to check the data in your err object.

In the success case, you're checking res.data.user.username Just try to look inside err before you are calling err.response.data.errors, obviously that err.response is undefined.

0
votes

Before passing your error message in toast, Check that by doing console.

.catch((error) => {
    if (error.response) {
      // Request made and server responded
      console.log(error.response.data);
      console.log(error.response.status);
      console.log(error.response.headers);
    } else if (error.request) {
      // The request was made but no response was received
      console.log(error.request);
    } else {
      // Something happened in setting up the request that triggered an Error
      console.log('Error', error.message);
    }
});
0
votes

This is not directly an answer and anyone is free to correct me since I am not a pro at React.js but because I managed to get a few things working thought I should post now my error came from the following;

First of all for this am using React Router v6 in my code

First in the Routes I needed to have added these two paths;

  { path: '/private', element: <PrivateRoute /> },
  { path: '/admin', element: <AdminRoute  /> },

And second of all was to convert history.push since its no longer supported in React.

This means I had to convert history.push to useNavigate using navigate in the following way;

      ?history.push('/admin')
      :history.push('/private');

The converted code is as below not forgetting to import useNavigate like import { useNavigate } from 'react-router-dom'; and then calling it as const navigate = useNavigate();

          // if authenticate but not admin redirect to / private
          // if admin redirect to /admin
          isAuth() && isAuth().role === 'admin'
              // ?history.push('/admin')
              // :history.push('/private');
              ?navigate('/admin')
              :navigate('/private')
          toast.success(`Hey ${res.data.user.username}, Welcome back!`);
        })

As you can see from my image Screenshot my error is cleared and the Chrome console is also clear and if you can Zoom in on the URL BAR you can notice the routes changed successfully from /login to /private; image