[Fixed] Data is undefined in my promise could not set Error properly [API problem/Front Problem ? ]

Issue

what i’m trying to do is to signup my user using simple form ,but suddenly i get this error also it seems that data (promise argument ) is undefined ,
Unhandled Runtime Error
TypeError: Cannot read property ‘message’ of undefined

(forgive my terminology)

frontend

import React,{useState} from "react";
import {signup} from '../../actions/auth'

const SignupComponent = () =>{
   const [values, setValues] = useState({
      name: "Fares",
      email: "[email protected]",
      password: "dccihdss",
      error: "",
      loading: false,
      message: "",
      showForm: true,
   });

   const {name,email,password,error,loading,message,showForm} = values 

   const handleSubmit = (e)=>{
        e.preventDefault();
        setValues({...values,loading:true,error:false})
        const user ={name,email,password}
        signup(user)
        .then(data => {
            console.log(data); //!!!!!!!this promise is returning 'undefined' , !!!!!!!!!!!!
            if(data.error){
                setValues({...values,error:data.error,loading:false});
            }else{
                setValues({
                  ...values,
                  name: "",
                  email: "",
                  password: "",
                  error: "",
                  loading: false,
                  message: data.message,
                  showForm: false,
                });
            }
        });
    }
    const handleChange = name => e => {
        setValues({ ...values, error:false, [name]: e.target.value });
    }
    const signupForm = () =>{
        return (
          <form onSubmit={handleSubmit}>
            <div className="form-group">
              <input
                value={name}
                onChange={handleChange('name')}
                type="text"
                className="form-control"
                placeholder="Type your name"
              />
            </div>
            <div className="form-group">
              <input
                value={email}
                onChange={handleChange("email")}
                type="email"
                className="form-control"
                placeholder="Type your email"
              />
            </div>
            <div className="form-group">
              <input
                value={password}
                onChange={handleChange('password')}
                type="password"
                className="form-control"
                placeholder="Type your password"
              />
            </div>
                <div>
                    <button className="btn btn-primary">Signup</button>
                </div>
          </form>
        );
    }
    return (
        <React.Fragment>{signupForm()}</React.Fragment>
    )
};

export default SignupComponent;

signup method (isomorphic-fetch)

import fetch from 'isomorphic-fetch';
import {API} from '../config'

export const signup = (user)=>{
    return fetch(`${API}/signup`, {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Contnet-Type": "application/json",
      },
      body: JSON.stringify(user)
    }).
    then((response) => {
      return response.json();
    }).catch((error) => console.log(error));
}

Auth API

exports.signup = (req, res) => {
  user.findOne({ email: req.body.email }).exec((err, user) => {
    if (user) {
      return res.status(400).json({
        error: "Email is taken",
      });
    }
    const { name, email, password } = req.body;
    let username = shortId.generate();
    let profile = `${process.env.CLIENT_URL}/profile/${username}`;

    let newUser = new User({ name, email, password, profile, username });

    newUser.save((err, success) => {
      if (err) {
        return res.status(400).json({
          error: "something is not correct",
        });
      }
      res.json({
        // user:success,
        message: "Signup success ! please Sign in ",
      });
    });
  });
};
exports.signin = (req, res) => {
  const { email, password } = req.body;
  //check if the user exist
  User.findOne({ email }).exec((err, user) => {
    if (err || !user) {
      return res.status(400).json({
        error: "User with that email does not exist , Please signup",
      });
    }
    //authentification
    if(!user.authenticate(password)){
        return res.status(400).json({
            error: "Email and password don't match",
          });
    }
    // generate token and send to client 
    const token = jwt.sign({ _id: user._id },process.env.JWT_SECRET,{expiresIn:'1d'});

    res.cookie("token", token, { expiresIn: "1d" });
 
    const {_id,username,name,email,role} = user
    return res.json({
        token,
        user:{_id,username,name,email,role}
    })
});
};

// FrontEnd dependencies

"dependencies": {
    "es6-promise-promise": "^1.0.0",
    "isomorphic-fetch": "^3.0.0",
    "next": "^10.1.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "reactstrap": "^8.9.0"
  },

backend dependencies

"dependencies": {
    "body-parser": "^1.19.0",
    "cookie-parser": "^1.4.5",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "express-jwt": "^6.0.0",
    "express-validator": "^6.10.0",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^5.12.2",
    "morgan": "^1.10.0",
    "nodemon": "^2.0.7",
    "shortid": "^2.2.16"
  }

Solution

Your signup method is an asynchronous call, it should return a promise. If you are already handling .then call in your handleSubmit method, then you need to remove the .then call from the signup method. Below is the updated code

import fetch from 'isomorphic-fetch';
import {API} from '../config'

// now, since fetch returns a promise, and signup method is returning fetch
// it is returning a promise on which we can call `.then` and `.catch` accordingly
export const signup = async (user) => {
    return fetch(`${API}/signup`, {
      method: "POST",
      headers: {
        Accept: "application/json",
        "Contnet-Type": "application/json",
      },
      body: JSON.stringify(user)
    })
}

Leave a Reply

(*) Required, Your email will not be published