使用AXIOS从React提交到Node / express时无法提交表单数据

时间:2018-09-06 09:16:23

标签: node.js mongodb reactjs api express

从表单向服务器提交数据时遇到问题。 我已经在api / userprofile的后端创建了一个API,并且能够使用POSTMAN成功创建一个配置文件。但是在尝试使用前端/浏览器时,出现错误:

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

其他错误是:

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;

这是前端反应代码:

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';

1 个答案:

答案 0 :(得分:1)

您的错误提示:

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

这意味着您将字符串值传递到应该是对象的位置。

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

在这里您说的应该是对象。这是对您执行的道具的验证。将此更改为字符串。它将解决问题。