我有两个redux动作,一个名为register
的动作有效,显示console.log
然而logIn
动作不显示的console.log,所以IM假设存在具有终极版调用在logIn
的动作。
这不是reducer的问题,因为操作应该能够调用console.log。
我想知道为什么redux不调用dispatch来执行logIn动作。即使出现错误,我也应该在console.log(err.response)
中收到一条错误消息,但是即使在控制台选项卡上也没有呈现。
actions / index.js
import axios from 'axios';
import { history } from '../components/Navbar';
export const SET_USER = "SET_USER";
export const lOG_FAIL = "lOG_FAIL";
export const REG_SUC = "REG_SUCCESS";
export const REG_FAIL = "REG_FAIL";
export const logIn = (user) => {
return (dispatch) => {
axios.post('/api/users/loginUser',{
username: user.username,
password: user.password
}).then( (res) => {
// localStorage.setItem('JWT', res.data.token);
// history.push('/dashboard');
dispatch({type: SET_USER, user});
}).catch((err)=> {
dispatch({type: lOG_FAIL, err});
console.log(err.response.data); // not even showing err console.
console.log('no console log that appears here either') // doesn't show console log
})
}
}
export const register = (user) => {
return (dispatch) => {
axios.post('/api/users/new',{
username: user.username,
password: user.password,
email: user.email
}).then( (res) => {
// console.log('success')
history.push('/signIn');
dispatch({type: REG_SUC, user});
}).catch((err)=> {
dispatch({type: REG_FAIL, err});
console.log(err.response.data); // shows console.log for this though.
})
}
}
减速器
import { SET_USER, REG_SUC, REG_FAIL, lOG_FAIL} from '../actions/';
const initialState = {
authError: null,
isAuthenticated: false,
token: null,
user: [],
getToken: localStorage.getItem('JWT')
}
export default (state = initialState, action) => {
switch (action.type) {
case SET_USER:
return ({
...state,
user:action.user,
token: action.payload,
isAuthenticated: true
});
case lOG_FAIL:
return({
...state,
authError:action.err
});
case REG_SUC:
return({
...state,
user:action.user,
isAuthenticated:true,
});
case REG_FAIL:
return({
...state,
authError:action.err.response.data
});
default:
return state
}
}
登录组件
class signIn extends Component{
constructor(props){
super(props)
this.state = {
formData:{
username:"",
password: ""
},
loggedEmail:"",
loginError: "",
myToken:"",
userLoggedIn: false,
emailBlank: true,
passwordBlank: true,
emailInvalid: false,
passwordInValid: false,
// token:localStorage.getItem('JWT')
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange = (e) =>{
e.preventDefault();
const { formData } = this.state;
this.setState({
formData: {
...formData,
[e.target.name]: e.target.value
}
});
}
handleSubmit = (e) => {
e.preventDefault();
const {formData} = this.state;
const {username,password} = formData;
this.setState({
username: this.state.username,
password: this.state.password
});
const creds = {
username, password
}
this.props.logIn(creds);
console.log(creds);
}
componentDidMount(){
}
render(){
if( this.props.token){
return(
<Redirect to="/dashboard"/>
);
}
return (
<div style={ {padding: '20px 100px'}}>
<h1>Sign In</h1>
<form onSubmit={this.handleSubmit}>
<TextField
id="outlined-name2"
label="Username"
className=""
style={{width: 560}}
name="username"
value={this.state.username}
onChange={this.handleChange}
margin="normal"
variant="outlined"
/>
<br></br>
<TextField
id="outlined-name"
label="Password"
name="password"
type="password"
style={{width: 560}}
className=""
value={this.state.password}
onChange={this.handleChange}
margin="normal"
variant="outlined"
/>
<br></br>
<Button variant="outlined" color="primary" type="submit">
Log In
</Button>
</form>
</div>
);
}
}
const mapStateToProps = (state) => ({
token: state.user.getToken
})
const mapDispatchToProps = (dispatch) => ({
logIn: (user) => dispatch(logIn(user))
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(signIn));
注册组件
import React, { Component } from 'react';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import axios from 'axios';
import { connect } from 'react-redux';
import {register} from '../actions/';
import { Redirect, withRouter } from 'react-router-dom';
class signUp extends Component{
constructor(props){
super(props)
this.state = {
formData:{
username:"",
password: "",
passwordConf:"",
email:""
},
passErr: "",
regSuccess: false
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange = (e) =>{
e.preventDefault();
const { formData } = this.state;
this.setState({
formData: {
...formData,
[e.target.name]: e.target.value
}
});
}
handleSubmit = (e) => {
e.preventDefault();
const {formData} = this.state;
const {username, email, password, passwordConf} = formData;
this.setState({
username: this.state.username,
password: this.state.password,
passwordConf: this.state.passwordConf,
email:this.state.email,
});
const creds = {
username, email, password
}
if(password === passwordConf){
this.props.register(creds);
}
else{
this.setState({
passErr: "Passwords Don't Match"
})
}
}
render(){
const {token } = this.props
if(token){
return <Redirect to='/dashboard'/>
}
return (
<div style={ {padding: '20px 100px'}}>
{this.props.error && (
<div style={{color:'red'}}>
{this.props.error}
</div>
)}
{this.state.passErr && (
<div style={{color:'red'}}>
{this.state.passErr}
</div>
)}
<h1>Sign Up</h1>
<form onSubmit={this.handleSubmit}>
<TextField
id="outlined-name"
label="Username"
style={{width: 560}}
name="username"
value={this.state.username}
onChange={this.handleChange}
margin="normal"
variant="outlined"
/>
<br></br>
<TextField
id="outlined-name"
label="Email"
className=""
style={{width: 560}}
name="email"
value={this.state.email}
onChange={this.handleChange}
margin="normal"
variant="outlined"
/>
<br></br>
<TextField
id="outlined-name"
label="Password"
name="password"
type="password"
style={{width: 560}}
className=""
value={this.state.password}
onChange={this.handleChange}
margin="normal"
variant="outlined"
/>
<br></br>
<TextField
id="outlined-name"
label="Confirm Password"
name="passwordConf"
type="password"
style={{width: 560}}
className=""
value={this.state.passwordConf}
onChange={this.handleChange}
margin="normal"
variant="outlined"
/>
<br></br>
<Button variant="outlined" color="primary" type="submit">
Sign Up
</Button>
</form>
</div>
);
}
}
const mapStateToProps = (state) => ({
token: state.user.getToken,
error: state.user.authError
})
const mapDispatchToProps = (dispatch) => ({
register: (user) => dispatch(register(user))
});
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(signUp));
后端
router.post('/loginUser', (req, res, next) => {
passport.authenticate('login', (err, user, info) => {
if (err) {
console.log(err);
}
if (info != undefined) {
console.log(info.message);
res.send(info.message);
} else {
req.logIn(user, err => {
models.User.findOne({
where: {
username: req.body.username,
},
}).then(user => {
const token = jwt.sign({ id: user.id }, 'nodeauthsecret');
res.status(200).send({
auth: true,
token: token,
message: 'user found & logged in',
});
});
});
}
})(req, res, next);
});
答案 0 :(得分:1)
在这种情况下,登录请求失败时将发布一个200
好的响应。因此,axios无法捕获该错误。修复响应状态可以在后端解决此问题。
res.status(401).send(info.message);