【问题标题】:props.actions `undefined` when using redux and react.js使用 redux 和 react.js 时的 props.actions `undefined`
【发布时间】: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) =&gt; {写成handleSubmit(event) =&gt; {吗?
  • 在您的 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


【解决方案1】:

我相信你的麻烦在于这条线。

export default Form.create()(Login);connect(null, mapDispatchToProps)(Login);

您只是导出 Form.create() 返回的内容,因此您的组件实际上并未连接到 redux。

要解决此问题,您需要执行以下操作。

export default Form.create(connect(null, matchDispatchToProps)(Login));

具体的语法有所不同,这取决于Form.create() 的用法,但这是基本思想。

【讨论】:

  • 我尝试了您的解决方案,它似乎有效,但表单未呈现。我也在控制台中收到了这个警告:Warning: Functions are not valid as a React child. This may happen if you return a Component instead of &lt;Component /&gt; from render. Or maybe you meant to call this function rather than return it.
  • 不幸的是,我不知道Form.create() 的确切用法,但我只是想指出您需要导出这两个高阶组件的组合。对不起,我不能说得更清楚。
  • 这是文档:ant.design/components/form 感谢您的帮助!
  • 我使用了来自github.com/acdlite/recompose 的 compose(),我想我已经修复了所有问题,但现在又遇到了另一个错误:Error: Actions must be plain objects. Use custom middleware for async actions.
猜你喜欢
  • 2017-03-30
  • 2018-02-21
  • 2021-01-15
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
  • 2021-09-20
  • 2018-07-05
  • 1970-01-01
相关资源
最近更新 更多