失败的道具类型:prop“ action”在``测试''中按要求标记,但其值是``未定义''
我正在使用 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);
loginAction.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);});
}
loginReducer.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;
}
}
运行页面时出现此错误:失败的 prop 类型:prop
actions
在
Testing
中被标记为必需,但其值为
undefined
。此外,
handleChange
方法抛出了以下错误:
Uncaught TypeError: Cannot set property 'username' of null
.
更新: 我的 store.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 { 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
。