从表单向服务器提交数据时遇到问题。 我已经在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';
答案 0 :(得分:1)
您的错误提示:
Invalid prop `errors` of type `string` supplied to `CreateProfile`, expected `object`
这意味着您将字符串值传递到应该是对象的位置。
CreateProfile.propTypes={
profile:PropTypes.object.isRequired,
**errors:PropTypes.object.isRequired** }
在这里您说的应该是对象。这是对您执行的道具的验证。将此更改为字符串。它将解决问题。