我正在使用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;

  }
}


运行页面时,出现此错误:道具类型失败:道具actionsTesting中标记为必需,但其值为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访问其值;
这么说,不要在bind函数中使用render处理程序。在constructor中执行此操作,因为它将在每个handler调用上创建render的新实例。对性能不利。
至于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

关于javascript - Prop 类型失败: Prop “操作”在“测试”中标记为必需,但其值为“未定义”,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43939725/

10-11 13:19