失败的道具类型:道具"动作"在"测试"中标记为必需,但其值为"未定义&



我正在使用React和Redux创建一个简单的登录表单。我app.js是:

import React from 'react';
import { render } from 'react-dom';
import Input from 'react-toolbox/lib/input';
import {Button, IconButton} from 'react-toolbox/lib/button';
import PropTypes from 'prop-types';
import * as loginAction from '../actions/loginAction';
class Testing extends React.Component {
onLoginFormSubmit(event) {
event.preventDefault();
this.props.actions.Testing(this.state.username, this.state.password);
}
handleChange(name, value){
let state = this.state;
state[name] = value;
this.setState({state});
console.log(name); // cannot read property of null
console.log(value); // cannot read property of null
}
render() {
console.log(this.props);
return (
<div>
<form name="Login" onSubmit={(e) => this.onLoginFormSubmit(e)}>
<Input type="text" name="username" value="" placeholder="Email Id"  tabIndex="1" onChange={this.handleChange.bind(this, 'username')} />
<Input name="password" value="" placeholder="Password" type="password" tabIndex="2" onChange={this.handleChange.bind(this, 'password')} />                  <Button type="submit" className="m-t-20 blue-btn" label="Sign in" tabIndex="3" /> 
</form>
</div>
);
}
}
Testing.propTypes = {
loginAction: PropTypes.object.isRequired,
};
function mapStateToProps(state, ownProps) {
return {
loginResponse: state.loginResponse
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(loginAction, dispatch)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Testing);

登录操作.js文件为:

export function loginError(error){
return  { error, type: LOGIN_FAILED };
}
export function loginSuccess(response){
return dispatch => {
dispatch({ response, type: LOGIN_SUCCESS});
};
}
export function loginRequest(username, password){
const user = {username: username, password: password};
return { user, type: LOGIN_ATTEMPT };
}

export function login(username, password) {
console.log("User Data: ", username, password);
return dispatch =>
fetch('url', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username: username,
password: password
}),
})
.then(response => {
console.log("I'm here");
if(response.status >= 200 && response.status < 300){
console.log("Response; ", response);
dispatch(loginSuccess(response));
} else {
const error = new Error(response.statusText);
error.response = response;
dispatch(loginError());
throw error;
}
})
.catch(error => { console.log('Request Failed: ', error);});
}

而登录Reducer.js文件是:

import {
LOGIN_SUCCESS,
LOGIN_FAILED,
LOGIN_ATTEMPT
} from '../actions/loginAction';
import Immutable from 'immutable';
const initialState = new Immutable.Map({
username: '',
password: '',
isLoggingIn: false,
isLoggedIn: false,
error: null
});
export default function user(state = initialState, action){
switch (action.type){
case LOGIN_ATTEMPT:
console.log("LOGIN_ATTEMPT: ",action.user);
return state.merge({
isLoggingIn: true,
isLoggedIn: false,
username: action.user.username,
password: action.user.password
});
case LOGIN_FAILED:
console.log("LOGIN_FAILED: ");
return state.merge({
error: action.error,
isLoggingIn: false,
isLoggedIn: false
});
case LOGIN_SUCCESS:
console.log("LOGIN_SUCCESS: ",action);
return state.merge({
error: null,
isLoggingIn: false,
isLoggedIn: true
})
break;
default:
return state;
}
}

运行页面时,我收到此错误: 失败的道具类型:道具actionsTesting中标记为必需,但其值为undefined。此外handleChange该方法会抛出以下错误:Uncaught TypeError: Cannot set property 'username' of null.

更新:我的商店.js代码是:

import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import thunk from 'redux-thunk';
import user from '../reducers/loginReducer';
const store = createStore(
user,
applyMiddleware(thunk)
);
var routes =(
<Provider store={store}>
<Router history={browserHistory}>
<Route path="/" component={Main}>
<Route path="/testing" component={Testing}>
</Router>
</Provider>
);

我现在不想使用 redux-form。

函数handleChange应该只获取一个事件作为参数。
handleChange(e)此事件附加到目标元素,因此您可以通过e.target.value访问其值;
话虽如此,请不要在render函数中bind处理程序。 在constructor中执行此操作,因为它将在每次render调用上创建handler的新实例。 对性能不利。 至于redux流,你应该使用connect.
export default connect(mapStateToProps, mapDispatchToProps)(Testing).
编辑
再看一下你的代码后,除了你没有使用connect将组件连接到redux之外,你正在将一个错误的对象映射到mapDispatchToProps
在此代码中,您将使用loginAction

function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(loginAction, dispatch)
}
}  

但是您从未导入过它,而是使用了名称import:
import { loginSuccess, loginRequest, login } from '../actions/loginAction';
导入所有内容并将其传递给mapDispatchToProps的一种可能方法是:
import * as loginAction from '../actions/loginAction';
您犯的另一个错误是在propTypes上用不同的名称命名此对象,您将其命名为actions而不是loginAction

Testing.propTypes = {
actions: PropTypes.object.isRequired,
};

您将需要相同的名称:

Testing.propTypes = {
loginAction: PropTypes.object.isRequired,
};

再一次不要忘记connect!!

我相信您需要将组件连接到 redux。

import { connect } from 'react-redux'
// your code
export default connect(mapStateToProps, mapDispatchToProps)(Testing)

不要忘记从上课前删除export default

编辑:如果您打算修改组件的本地状态,请使用setState

最新更新