I've stumbled upon a problem whilst developing my app and I am now stuck. My web app is a very simple interface for registering/logging/modifying users using MERN stack along with Redux and Axios. While calling /update endpoint like so:
export const updateUser = (userData, history) => dispatch => {
let token = localStorage.getItem("jwtToken");
axios.defaults.headers.common["Authorization"] = token;
console.log(token);
axios
.patch('http://localhost:5000/api/users/update', userData, { crossdomain: true })
.then(res => {
history.push("/dashboard");
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
However, I keep getting cors authorization error( "missing authorization token in CORS header „Access-Control-Allow-Headers” in CORS OPTIONS request" ), although in the above code you can clearly see I;m setting it explicitly (I set it even one more time earlier, just after user login).
I had similar CORS issues previously with login/register post requests, but they were fixed when I added in the backend:
router.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
res.header("Access-Control-Allow-Methods", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Shouldn't I have the same problem earlier, when calling the database with login/register post requests? The assigned token is not empty and all the endpoints work fine when tested with Postman. I've run out of ideas what to do.
This is the calling component:
import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { updateUser } from "../actions/authActions";
import { deleteUser } from "../actions/authActions";
import classnames from "classnames";
class DataChange extends Component {
constructor() {
super();
this.state = {
name: "",
email: "",
password: "",
password2: "",
errors: {}
};
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({
errors: nextProps.errors
});
}
}
onChange = e => {
this.setState({ [e.target.id]: e.target.value });
};
onDeleteClick = e =>{
e.preventDefault();
this.props.deleteUser(this.props.auth.user.id);
}
onSubmit = e => {
e.preventDefault();
const newUser = {
id: this.props.auth.user.id,
name: this.state.name,
email: this.state.email,
password: this.state.password,
password2: this.state.password2
};
console.log(newUser);
this.props.updateUser(newUser, this.props.history);
};
render() {
const { errors } = this.state; return (
<div className="container">
<div className="row">
<div className="col s8 offset-s2">
<Link to="/dashboard" className="btn-flat waves-effect">
<i className="material-icons left">keyboard_backspace</i> Back to
home
</Link>
<div className="col s12" style={{ paddingLeft: "11.250px" }}>
<h4>
<b>Zmień</b> dane
</h4>
</div>
<form noValidate onSubmit={this.onSubmit}>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.name}
error={errors.name}
id="name"
type="text"
className={classnames("", {
invalid: errors.name
})}
/>
<label htmlFor="name">Name</label>
<span className="red-text">{errors.name}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.email}
error={errors.email}
id="email"
type="email"
className={classnames("", {
invalid: errors.email
})}
/>
<label htmlFor="email">Email</label>
<span className="red-text">{errors.email}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.password}
error={errors.password}
id="password"
type="password"
className={classnames("", {
invalid: errors.password
})}
/>
<label htmlFor="password">Password</label>
<span className="red-text">{errors.password}</span>
</div>
<div className="input-field col s12">
<input
onChange={this.onChange}
value={this.state.password2}
error={errors.password2}
id="password2"
type="password"
className={classnames("", {
invalid: errors.password2
})}
/>
<label htmlFor="password2">Confirm Password</label>
<span className="red-text">{errors.password2}</span>
</div>
<div className="col s6" style={{ paddingLeft: "11.250px" }}>
<button
style={{
width: "150px",
borderRadius: "3px",
letterSpacing: "1.5px",
marginTop: "1rem"
}}
type="submit"
className="btn btn-large waves-effect waves-light hoverable blue accent-3"
>
Wprowadź zmiany
</button>
</div>
<div className="col s6" style={{ paddingLeft: "11.250px" }}>
<button
style={{
width: "150px",
borderRadius: "3px",
letterSpacing: "1.5px",
marginTop: "1rem"
}}
onClick={this.onDeleteClick}
className="btn btn-large waves-effect waves-light hoverable red accent-3"
>
Usuń użytkownika
</button>
</div>
</form>
</div>
</div>
</div>
);
}
}
DataChange.propTypes = {
updateUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
auth: state.auth,
errors: state.errors
});
const mapDispatchToProps = {
deleteUser,
updateUser,
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(withRouter(DataChange));