0

I am having issues while submitting data from a form to the server. I have created an API in backend at api/userprofile and I am able to successfully create a profile using POSTMAN. But while trying using front-end/browser I am getting an error:

POST http://localhost:3000/api/userprofile 401 (Unauthorized)

The other errors are:

index.js:2178 Warning: Failed prop type: Invalid prop `errors` of type `string` supplied to `CreateProfile`, expected `object`.
    in CreateProfile (created by Route)
    in Route (created by withRouter(CreateProfile))
    in withRouter(CreateProfile) (created by Connect(withRouter(CreateProfile)))
    in Connect(withRouter(CreateProfile)) (created by Route)
    in Route (at App.js:41)
    in div (at App.js:37)
    in div (at App.js:34)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:33)
    in Provider (at App.js:32)
    in App (at index.js:8)

api/userprofile.js

const express = require('express');
const router = express.Router();
const mongoose=require('mongoose');
const passport=require('passport');

//loading validation after creating the userprofie valdiation
const validateProfileInput=require('../../validation/userprofile');
const validateExperienceInput=require('../../validation/experience');
//bring profile schema model

const Profile=require('../../models/Profile');

//bringing user schema model
const User=require('../../models/User');

//testing this api 
router.get('/demo', (req, res) => res.json({ msg: 'Profile Works' }));
//get request
//now need to check for the user who is trying to login
router.get('/',passport.authenticate('jwt', { session: false }),(req, res) => {
    //initializing this as empty because need to add error msg   
    const errors = {};
//fetch current user's profile and finding from profile model
//findone is a mongoose method which will find a specifc{single} thing
        Profile.findOne({ user: req.user.id }) .populate('user', ['name']).then(profile => {
           //if not found display error msg
            if (!profile) {
              errors.noprofile = 'no profile exists for this person';
              return res.status(404).json(errors);
            }
            //if found then show proifle
            res.json(profile);
          })
          .catch(err => res.status(404).json(err));
      }
    )
//to see all profiles at api/userprofile/all

    router.get('/all',(req,res)=>{
        Profile.find()
        .populate('user',['name'])
        .then(profiles=>{
            if(!profiles){
                errors.noprofile='no profiles';
                return res.status(404).json(errors);
            }
            res.json(profiles);
        })
        .catch(err=>res.status(404).json({profile:'no profiles'}));
    })
//getting profile by name

    router.get('/profilename/:profilename',(req,res)=>{
        Profile.findOne({profiename:req.params.profiename})
        .populate('user',['name'])
        .then(profile=>{
            if(!profile){
                errors.noprofile='there is no profile';
                res.status(400).json(errors);
            }
            res.json(profile);
        })
        .catch(err=>res.status(404).json(err));
    })
//getting profile by id

    router.get('/users/:users_id',(req,res)=>{
        Profile.findOne({profiename:req.params.profiename})
        .populate('user',['name'])
        .then(profile=>{
            if(!profile){
                errors.noprofile='there is no profile';
                res.status(400).json(errors);
            }
            res.json(profile);
        })
        .catch(err=>res.status(404).json(err));
    })
//post request
    router.post(
        '/',
        passport.authenticate('jwt', { session: false }),
        (req, res) => {
        const {errors,isValid}=validateProfileInput(req.body);

        //check validation
        if(!isValid){
            return res.status(400).json(errors);
        }
        //getting fields and adding in an obj
        const fields={};
        fields.user=req.user.id;

        //checking if its sent from handle
        if(req.body.profilename)fields.profilename=req.body.profilename;
        if(req.body.company)fields.company=req.body.company;
        if(req.body.location)fields.location=req.body.location;

        //so splitting skills into an array when seperated by ','

        if(typeof req.body.skills!=='undefined')
            fields.skills=req.body.skills.split(',');

//searching by id and if profile has then update

        Profile.findOne({user:req.user.id}).then(profile=>{
            if(profile){
                Profile.findOneAndUpdate({user:req.user.id},{$set:fields},{new:true})
                .then(profile=>res.json(profile));
            }
            else{
                //checking if there
                Profile.findOne({profiename:fields.profilename}).then(profile=>{
                    if(profile){
                        errors.profiename='profile already there'
                        res.status(400).json(errors);
                    }
                    //saving  and making new if not
                    new Profile(fields).save().then(profile=>res.json(profile));
                })
            }
        })
          }
        );

//post req to add exp
router.post(
    '/experience',
    passport.authenticate('jwt', { session: false }),
    (req, res) => {
      const { errors, isValid } = validateExperienceInput(req.body);

      // Check Validation
      if (!isValid) {
        // Return any errors with 400 status
        return res.status(400).json(errors);
      }
  //to add new experience
      Profile.findOne({ user: req.user.id }).then(profile => {
        const newExperience = {
          title: req.body.title,
          company: req.body.company,
          location: req.body.location,
          from: req.body.from,
          to: req.body.to,

          description: req.body.description
        };

        // Add to exp array
        profile.experience.unshift(newExperience);

        profile.save().then(profile => res.json(profile));
      });
    }
  );

  //after adding if user wants to delete the experience
  router.delete(
    '/experience/:exp_id',
    passport.authenticate('jwt', { session: false }),
    (req, res) => {
      const { errors, isValid } = validateExperienceInput(req.body);

      // Check Validation
      if (!isValid) {
        // Return any errors with 400 status
        return res.status(400).json(errors);
      }

      Profile.findOne({ user: req.user.id }).then(profile => {
        const remove=profile.experience
        .map(item=>item.id)
        .indexof(req.params.exp_id);
        //splicing out of array at index 1
        profile.experience.splice(remove,1)

        //saving
        profile.save().then(profile=>res.json(profile));
      })
      .catch(err=>res.status(404).json(err));
    }
  );


module.exports = router;

This is the front-end react code:

import React, { Component } from 'react'
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import TextField from '../common/TextField';
import {withRouter} from 'react-router-dom';
import TextAreaField from '../common/TextAreaField';
import SelectListGroup from '../common/SelectListGroup';
import {createProfile} from '../../actions/userprofileAction';




class CreateProfile extends Component {
    constructor(props){
        super(props);
        this.state={
            profilename:'',
            location:'',
            skills:'',
            interest:'',
            bio:'',
            errors:{}

        }
        this.onChange=this.onChange.bind(this);
        this.onSubmit=this.onSubmit.bind(this);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.errors) {
          this.setState({ errors: nextProps.errors });
        }
      }
    onSubmit(e) {
        e.preventDefault();

        const profileData={
            profilename:this.state.profilename,
            location:this.state.location,
            skills:this.state.skills,
            interest:this.state.interest,
            bio:this.state.bio
        }

        this.props.createProfile(profileData, this.props.history);
      }
     onChange(e) {
    this.setState({ [e.target.name]: e.target.value });
  }
  render() {
      const {errors}=this.state;
    return (
      <div className='createprofile'>
      <div className='container'>
      <div className="row">
      <div className="col-md-8 m-auto">
        <h1 className="display-4 text-center">Create Your Profile</h1>
        <form onSubmit={this.onSubmit}>
        <TextField
        placeholder="Profile name"
        name="profilename"
        value={this.state.profilename}
        onChange={this.onChange}
        error={errors.profilename}
        info="Enter the Profilename you want to keep"/>
        <TextField
        placeholder="Location"
        name="location"
        value={this.state.location}
        onChange={this.onChange}
        error={errors.location}
        info="City (eg. Hamilton)"/>
        <TextField
        placeholder="Skills"
        name="skills"
        value={this.state.skills}
        onChange={this.onChange}
        error={errors.skills}
        info="Enter the skills seperated by Commas (eg. HTML,Management, Marketing, Customer Service)"/>

        <TextField
        placeholder="Interests"
        name="interest"
        value={this.state.interest}
        onChange={this.onChange}
        error={errors.interest}
        info="What are your interests? (eg. Blogging, Football, Cooking)"/>
         <TextAreaField
        placeholder="Bio"
        name="bio"
        value={this.state.bio}
        onChange={this.onChange}
        error={errors.bio}
        info="Introduce yourself briefly"/>
        <input
                  type="submit"
                  value="Create my PROFILE"
                  className="btn btn-info btn-block mt-4"
                />
        </form>
        </div>
      </div>
      </div>
      </div>
    )
  }
}
CreateProfile.propTypes={
    profile:PropTypes.object.isRequired,
    errors:PropTypes.object.isRequired
}
const mapStateToProps = state => ({
    profile: state.profile,
    errors: state.errors
  })


export default connect(mapStateToProps, { createProfile })(withRouter(CreateProfile));

userprofileAction.js:

import axios from 'axios';
import {GET_USERPROFILE,PROFILE_LOADING,GET_ERRORS,CLEAR_CURRENT_PROFILE} from './types';

//getting current profile
export const getProfile=()=>dispatch=>{
    //dispatching loading state before req
    dispatch(profileLoading());
    axios.get('/api/userprofile')
    .then(res=>
    dispatch({
        type:GET_USERPROFILE,
        payload:res.data
    }))
    .catch(err=>
    dispatch({
        type:GET_USERPROFILE,
        payload:{}
    }))
}


 // Create Profile
export const createProfile = (profileData, history) => dispatch => {
    axios
      .post('/api/userprofile', profileData)
      .then(res => history.push('/dashboard'))
      .catch(err =>
        dispatch({
          type: GET_ERRORS,
          payload: err.response.data
        })
      );
  };
//loading the profile
export const profileLoading=()=>{
    return{
        type:PROFILE_LOADING
    }
}
//clearing profile
export const clearcurrentprofile=()=>{
    return{
        type:CLEAR_CURRENT_PROFILE
    }
}

types.js:

export const GET_ERRORS='GET_ERRORS';
export const SET_CURRENT_USER = 'SET_CURRENT_USER';
export const GET_USERPROFILE='GET_USERPROFILE';
export const PROFILE_LOADING = 'PROFILE_LOADING';
export const CLEAR_CURRENT_PROFILE='CLEAR_CURRENT_PROFILE';
export const NO_PROFILE_FOUND='NO_PROFILE_FOUND';
export const GET_PROFILES='GET_PROFILES';
2
  • You seem to be defining errors={} as an object and is receiving an string. Commented Sep 6, 2018 at 9:29
  • Are you setting any headers when doing the request by postman? Also, are you defining any proxy on axios? If so can you post how is the proxy configured? Commented Sep 6, 2018 at 9:31

1 Answer 1

1

Your error says:

Invalid prop `errors` of type `string` supplied to `CreateProfile`, expected `object`

That means you are passing string value where it should be object.

CreateProfile.propTypes={
profile:PropTypes.object.isRequired,
**errors:PropTypes.object.isRequired** }

Here you are saying it should be object. This is validation of props enforced by you. Change this to string. It will resolve the issue.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.