I am trying to make an app with the MERN Stack and have run into an issue. My app allows a “create profile” and “edit profile” component that uses the same API route since its a post request that has very similar actions. When I try to create a profile, everything works fine, but when I try to edit the profile I am running into an error. First of all, when I click the submit button (that calls the axios.post() route from the edit profile) the redux types don’t show up, and in 2 mins the application crashes. Secondly, it works fine in postman.
Here is the code in question
profile action
//create or update a profile
export const createProfile = (
formData,
history,
edit = false
) => async dispatch => {
try {
const config = {
headers: {
"Content-Type": "application/json"
}
};
const res = await axios.post("/api/profile", formData, config);
dispatch({ type: GET_PROFILE, payload: res.data });
dispatch(setAlert(edit ? "Profile Updated" : "Profile Created", "success"));
if (!edit) {
history.push("/dashboard");
}
} catch (err) {
//const errors = err.response.data.errors;
if (err.response) {
//errors.forEach(error => dispatch(setAlert(error.msg, "danger")));
dispatch(setAlert("response error", "danger"));
} else if (err.request) {
console.log(err.request);
//dispatch(setAlert("req error", "danger"));
} else {
dispatch(setAlert("another error", "danger"));
}
dispatch({
type: PROFILE_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
});
}
};
API route
// @route POST api/profile
// @desc create or update a profile
// @access Public
router.post(
"/",
[
auth,
[
check("status", "Status is required")
.not()
.isEmpty(),
check("skills", "Skills is required")
.not()
.isEmpty()
]
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const {
company,
website,
bio,
location,
skills,
status,
githubusername,
youtube,
facebook,
twitter,
linkedin,
instagram
} = req.body;
const profileFields = {};
profileFields.user = req.user.id;
if (company) profileFields.company = company;
if (website) profileFields.website = website;
if (bio) profileFields.bio = bio;
if (location) profileFields.location = location;
if (skills) {
profileFields.skills = skills.split(",").map(skill => skill.trim());
}
if (status) profileFields.status = status;
if (githubusername) profileFields.githubusername = githubusername;
profileFields.social = {};
if (youtube) profileFields.social.youtube = youtube;
if (facebook) profileFields.social.facebook = facebook;
if (twitter) profileFields.social.twitter = twitter;
if (linkedin) profileFields.social.linkedin = linkedin;
if (instagram) profileFields.social.instagram = instagram;
try {
let profile = await Profile.findOne({ user: req.user.id });
if (profile) {
//update
profile = await Profile.findOneAndUpdate(
{ user: req.user.id },
{ $set: profileFields },
{ new: true }
);
return res.json(profile);
}
//create
profile = new Profile(profileFields);
await profile.save();
return res.json(profile);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
}
);
front end component this issue arises in
import React, { useState, Fragment, useEffect } from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { createProfile, getCurrentProfile } from "../../actions/profile";
import { Link, withRouter } from "react-router-dom";
const EditProfile = ({
profile: { profile, loading },
createProfile,
getCurrentProfile,
history
}) => {
const [formData, setFormData] = useState({
company: "",
website: "",
location: "",
status: "",
skills: "",
githubusername: "",
bio: "",
twitter: "",
facebook: "",
instagram: "",
linkedin: "",
youtube: ""
});
const [displaySocialInputs, toggleSocialInputs] = useState(false);
useEffect(() => {
getCurrentProfile();
setFormData({
company: loading || !profile.company ? "" : profile.company,
website: loading || !profile.website ? "" : profile.website,
location: loading || !profile.location ? "" : profile.location,
status: loading || !profile.status ? "" : profile.status,
skills: loading || !profile.skills ? "" : profile.skills,
githubusername:
loading || !profile.githubusername ? "" : profile.githubusername,
bio: loading || !profile.bio ? "" : profile.bio,
twitter: loading || !profile.social ? "" : profile.social.twitter,
facebook: loading || !profile.social ? "" : profile.social.facebook,
instagram: loading || !profile.social ? "" : profile.social.instagram,
linkedin: loading || !profile.social ? "" : profile.social.linkedin,
youtube: loading || !profile.social ? "" : profile.social.youtube
});
}, [loading, getCurrentProfile]);
const {
company,
website,
location,
status,
skills,
githubusername,
bio,
twitter,
facebook,
instagram,
linkedin,
youtube
} = formData;
const onChange = e =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = e => {
e.preventDefault();
createProfile(formData, history);
console.log("updating");
};
return (
<Fragment>
<h1 className='large text-primary'>Edit Your Profile</h1>
<p className='lead'>
<i className='fas fa-user'></i> Let's get some information to make your
profile stand out
</p>
<small>* = required field</small>
<form className='form' onSubmit={e => onSubmit(e)}>
<div className='form-group'>
<select name='status' value={status} onChange={e => onChange(e)}>
<option value='0'>* Select Professional Status</option>
<option value='Developer'>Developer</option>
<option value='Junior Developer'>Junior Developer</option>
<option value='Senior Developer'>Senior Developer</option>
<option value='Manager'>Manager</option>
<option value='Student or Learning'>Student or Learning</option>
<option value='Instructor'>Instructor or Teacher</option>
<option value='Intern'>Intern</option>
<option value='Other'>Other</option>
</select>
<small className='form-text'>
Give us an idea of where you are at in your career
</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Company'
name='company'
value={company}
onChange={e => onChange(e)}
/>
<small className='form-text'>
Could be your own company or one you work for
</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Website'
name='website'
value={website}
onChange={e => onChange(e)}
/>
<small className='form-text'>
Could be your own or a company website
</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Location'
name='location'
value={location}
onChange={e => onChange(e)}
/>
<small className='form-text'>
City & state suggested (eg. Boston, MA)
</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='* Skills'
name='skills'
value={skills}
onChange={e => onChange(e)}
/>
<small className='form-text'>
Please use comma separated values (eg. HTML,CSS,JavaScript,PHP)
</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Github Username'
name='githubusername'
value={githubusername}
onChange={e => onChange(e)}
/>
<small className='form-text'>
If you want your latest repos and a Github link, include your
username
</small>
</div>
<div className='form-group'>
<textarea
placeholder='A short bio of yourself'
name='bio'
value={bio}
onChange={e => onChange(e)}
></textarea>
<small className='form-text'>Tell us a little about yourself</small>
</div>
<div className='my-2'>
<button
type='button'
className='btn btn-light'
onClick={() => toggleSocialInputs(!displaySocialInputs)}
>
Add Social Network Links
</button>
<span>Optional</span>
</div>
{displaySocialInputs && (
<Fragment>
<div className='form-group social-input'>
<i className='fab fa-twitter fa-2x'></i>
<input
type='text'
placeholder='Twitter URL'
name='twitter'
value={twitter}
onChange={e => onChange(e)}
/>
</div>
<div className='form-group social-input'>
<i className='fab fa-facebook fa-2x'></i>
<input
type='text'
placeholder='Facebook URL'
name='facebook'
value={facebook}
onChange={e => onChange(e)}
/>
</div>
<div className='form-group social-input'>
<i className='fab fa-youtube fa-2x'></i>
<input
type='text'
placeholder='YouTube URL'
name='youtube'
value={youtube}
onChange={e => onChange(e)}
/>
</div>
<div className='form-group social-input'>
<i className='fab fa-linkedin fa-2x'></i>
<input
type='text'
placeholder='Linkedin URL'
name='linkedin'
value={linkedin}
onChange={e => onChange(e)}
/>
</div>
<div className='form-group social-input'>
<i className='fab fa-instagram fa-2x'></i>
<input
type='text'
placeholder='Instagram URL'
name='instagram'
value={instagram}
onChange={e => onChange(e)}
/>
</div>
</Fragment>
)}
<input type='submit' className='btn btn-primary my-1' />
<Link className='btn btn-light my-1' to='/dashboard'>
Go Back
</Link>
</form>
</Fragment>
);
};
EditProfile.propTypes = {
createProfile: PropTypes.func.isRequired,
profile: PropTypes.object.isRequired,
getCurrentProfile: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
profile: state.profile
});
export default connect(mapStateToProps, { createProfile, getCurrentProfile })(
withRouter(EditProfile)
);
here is the errors I get in the console after it stalls and crashes
POST http://localhost:3000/api/profile net::ERR_EMPTY_RESPONSE
I’ve opened the networks tab and when I clicked on the response error, it said “failed to load response data” so not even that worked
Any help is appreciated
2
Answers
Check out the steps below: (It may help)
First-step:
You must use the redux async action middleware like(redux-thunk, redux-saga) to handle the api requests.
Second-step:
When you use the axios for handle the api requests, check the headers like(Authorization, …) and data that you pass correctly:
Example
Third-step:
Try this it may help, its working fine for me.