【发布时间】:2018-03-07 16:14:08
【问题描述】:
我正在关注此链接中的教程:http://www.thegreatcodeadventure.com/react-redux-tutorial-part-ii-react-router-and-container-components/
但是当handleSubmit() 函数被触发时,我得到一个错误:
TypeError: 无法读取未定义的属性“logInUser”
确实,当我尝试登录 this.props.actions 时,它是未定义的,但我不明白为什么。有什么遗漏吗?
我正在使用 Antd 作为 UI 框架。
组件
import React, { Component } from 'react';
import { Form, Icon, Input, Button, Checkbox } from 'antd';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as sessionActions from './actions/sessionActions';
const FormItem = Form.Item;
class Login extends Component {
constructor(props){
super(props);
this.state = {credentials: {username: '', password: ''}};
this.handleSubmit = this.handleSubmit.bind(this);
this.onChange = this.onChange.bind(this);
}
onChange(event) {
const field = event.target.name;
const credentials = this.state.credentials;
credentials[field] = event.target.value;;
return this.setState({credentials: credentials});
}
handleSubmit = (event) => {
event.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
//console.log(this.props.actions);
this.props.actions.logInUser(this.state.credentials);
}
});
}
render() {
const { getFieldDecorator } = this.props.form;
return (
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator('userName', {
rules: [{ required: true, message: 'username missing!' }],
})(
<Input
name="username"
value={this.state.credentials.username}
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
placeholder="Username o email"
onChange={this.onChange}/>
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Password missing!' }],
})(
<Input
name="password"
value={this.state.credentials.password}
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
type="password"
placeholder="Password"
onChange={this.onChange}/>
)}
</FormItem>
<FormItem>
{getFieldDecorator('remember', {
valuePropName: 'checked',
initialValue: false,
})(
<Checkbox>Ricordami</Checkbox>
)}
<Button type="primary" htmlType="submit" className="login-form-button">
Log in
</Button>
</FormItem>
</Form>
);
}
}
const mapDispatchToProps = (dispatch) => {
return {
actions: bindActionCreators(sessionActions, dispatch)
};
}
export default Form.create()(Login);connect(null, mapDispatchToProps)(Login);
sessionReducer.js
import * as types from '../actions/actionTypes';
import initialState from './initialState';
export default function sessionReducer(state = initialState.session, action) {
switch(action.type) {
case types.LOG_IN_SUCCESS:
this.context.history.push('/')
return !!sessionStorage.jwt
default:
return state;
}
}
sessionActions.js
import * as types from './actionTypes';
import sessionApi from '../api/sessionApi';
export function loginSuccess() {
return {type: types.LOG_IN_SUCCESS}
}
export function logInUser(credentials) {
return function(dispatch) {
return sessionApi.login(credentials).then(response => {
sessionStorage.setItem('jwt', response.jwt);
dispatch(loginSuccess());
}).catch(error => {
throw(error);
});
};
}
更新 我在@Chaim Friedman 的帮助下解决了这个问题,但现在我遇到了另一个错误:
错误:动作必须是普通对象。使用自定义中间件进行异步操作。
但我使用 redux-thunk 作为中间件。如果有帮助,这里是登录功能:
sessionApi.js
import React from 'react'
var axios = require('axios');
var qs = require('qs');
class SessionApi {
static login(credentials){
axios.post('http://localhost:5000/login', qs.stringify({auth: credentials}))
.then(response => {
console.log(response);
return response.json();
}),
error => {
console.log(error);
return error;
};
}
}
【问题讨论】:
-
你试过把
handleSubmit = (event) => {写成handleSubmit(event) => {吗? -
在您的 mapDispatchToProe 中,您可以控制台记录 bindActionCreators 返回的内容吗?找出您在分配时设置的操作。
-
您还绑定了这个上下文两次。一次使用类属性分配,一次使用构造函数中的重新分配绑定。应该选择一个并与之保持一致。
-
我现在不知道是否是你所说的,但我认为这就是 bindActionCreators 返回的内容:
mapDispatchToProps(dispatch) { return { actions: Object(__WEBPACK_IMPORTED_MODULE_2_redux__["b" /* bindActionCreators */])(__WEBPACK_IMPORTED_MODULE_4__actions_sessionActions__, dispatch) }; }
标签: javascript reactjs react-redux antd