我不知道为什么我的this.props在handleSubmit上显示未定义。我已尽一切可能。当我在mapStateToProps中记录状态时,我看到了动作已调度的内容,但是this.props没有采取该动作。
当我输入错误的详细信息时,这就是我在记录器中得到的(https://imgur.com/a/AXixWn9) 我已经在网上搜索,但没有任何线索。我已经调试了几个小时
Login.js
import React from 'react';
import { NavLink } from 'react-router-dom';
import { Redirect } from 'react-router';
import qs from 'qs';
import { connect } from 'react-redux';
import Outer from '../templates/outer';
import history from '../../_helpers/history';
import routes from '../../services/urls';
import apiRequest from '../../services/api';
import loginUser from '../../redux/actions/authentication.action';
import { LOGIN_FAILURE, LOGIN_SUCCESS } from '../../redux/constants/authentication.constants';
import alertActions from '../../redux/actions/alert.actions';
class LoginComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
fields: {},
errors: {},
loginError: '',
submitted: false,
};
const { dispatch } = this.props;
dispatch(alertActions.clear());
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(field, e) {
const { fields } = this.state;
fields[field] = e.target.value;
this.setState({ fields });
}
handleValidation() {
const { fields } = this.state;
const errors = {};
let formIsValid = true;
// Login code
if (!fields.code) {
formIsValid = false;
errors.code = 'This field is required';
}
// Password
if (!fields.password) {
formIsValid = false;
errors.password = 'This field is required';
}
this.setState({ errors });
return formIsValid;
}
handleSubmit(e) {
e.preventDefault();
const { code, password } = this.state.fields;
this.setState({ submitted: true });
if (this.handleValidation()) {
this.setState({ submitted: true });
const payload = {
email: code,
// level: 'SYSTEM',
password,
};
const { dispatch } = this.props;
dispatch(loginUser(payload));
} else {
this.setState({ submitted: false });
}
}
render() {
const { loginError, submitted } = this.state;
return (
<Outer>
<form onSubmit={this.handleSubmit}>
<div className="mt-5" />
{loginError
&& <div className="alert alert-danger">{loginError}</div>
}
<label>Login Code</label>
<input type="text" className="form-control" onChange={this.handleChange.bind(this, 'code')} value={this.state.fields.code || ''} />
<div className="text-danger mt-1 mb-1">{this.state.errors.code}</div>
<br />
<label>Password</label>
<input type="password" className="form-control" onChange={this.handleChange.bind(this, 'password')} value={this.state.fields.password || ''} />
<div className="text-danger mt-1 mb-1">{this.state.errors.password}</div>
<br />
<button
className="btn btn-primary btn-block text-uppercase"
type="submit"
disabled={submitted}
>
{ !submitted ? 'Login to manage my cards' : 'loading...' }
</button>
<div className="row no-gutters mt-4">
<div className="col-md-12">
<NavLink to="/reset-password" className="grey">I have forgotten my password</NavLink>
</div>
</div>
</form>
</Outer>
);
}
}
function mapStateToProps(state) {
console.error(state);
const { auth } = state.authentication;
const { alert } = state.alert;
return { auth, alert };
}
export default connect(mapStateToProps)(LoginComponent);
store.js
export const store = createStore(
rootReducer,
applyMiddleware(
thunkMiddleware,
loggerMiddleware,
),
);
authentication.reducer.js
function loginReducer(state = {}, action) {
switch (action.type) {
case LOGIN_REQUEST:
return {
user_status: LOGIN_REQUEST,
user_data: action,
};
case LOGIN_SUCCESS:
return {
user_status: LOGIN_SUCCESS,
user_data: action,
};
case LOGIN_FAILURE:
return {
user_status: LOGIN_FAILURE,
user_data: action,
};
default:
return state;
}
}
export default loginReducer;
authentication.action.js
function loginUser(payload) {
function request(user) { return { type: LOGIN_REQUEST, user }; }
function success(response) { return { type: LOGIN_SUCCESS, response }; }
function failure(error) { return { type: LOGIN_FAILURE, error }; }
return (dispatch) => {
// const request = apiRequest(routes.LOGIN, 'POST', qs.stringify(payload));
// const ah = loginUser(qs.stringify(payload));
// console.log(ah);
dispatch(request(payload));
const fetch = apiRequest(routes.LOGIN, 'POST', qs.stringify(payload));
return fetch.then((response) => {
switch (response.status) {
case 400:
dispatch(failure(response));
dispatch(alertActions.error(response.data.description));
break;
case 200:
if (response.data.code === 0) {
localStorage.setItem('qwplx44', JSON.stringify(response.data));
dispatch(success(response.data));
history.push('/dashboard');
break;
}
dispatch(failure(response.data.description));
dispatch(alertActions.error(response.data.description));
break;
default:
return {};
}
}).catch((error) => {
dispatch(failure(error.response.data.message));
dispatch(alertActions.error(error.response.data.message.toString()));
// return false;
});
减根剂
const rootReducer = combineReducers({
authentication: loginReducer,
alert: alertReducer,
});
export default rootReducer;
答案 0 :(得分:1)
您没有正确连接组件。您正在尝试从不存在的状态中破坏键。在您的loginReducer上没有看到名为auth
的键。
因此,此行const { auth } = state.authentication;
将返回未定义。这就是为什么在记录道具auth
时未定义的原因。
取而代之的只是摘取您想要从状态中获取的内容,并且可以在销毁时将authentication
别名为auth
:)
const mapStateToProps = ({authentication: auth, alert}) => ({
auth,
alert
})
如果在发出请求后尝试使用化简器中存储的数据,则应使用componentDidUpdate
生命周期方法
componentDidUpdate(prevProps) {
const { auth: prevAuth } = prevProps
const { auth } = this.props
if (auth.user_status && ((!prevAuth.user_status && auth.user_status) || prevAuth.user_status !== auth.user_status)) {
// TODO handle response from api here
/* ex
if (auth.user_status === LOGIN_FAILURE) {
this.setState({loginFailure: auth.user_data})
}
*/
}
}
别的东西。
您没有将handleValidation
绑定到该类,但是正在尝试访问状态。
您正在this.setState({ submitted: true });
中两次致电handleSubmit
。第二个是多余的,不需要。
我将重构您的apiRequest
来处理qs.stringify
和错误/ auth /响应状态处理,因此您不必为每个api调用写同样的东西:)