0

I want to call a function/action when the form is submited but when the submit trigger React puts

TypeError: this.props.login(...) is undefined

This is the Login.js Page:

import React  from 'react';
import PropTypes from 'prop-types';
import Empty from '../Layouts/Empty';
import { Button }  from '../UI/Button';
import axios from 'axios'
import Notifications, {notify} from 'react-notify-toast';
import { connect } from 'react-redux'
import { login } from '../../actions/login'

class LoginForm extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
        email: '',
        password: '',
        isLoading: false
    };
    this.onChange = this.onChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  onChange(e) {
      this.setState({ [e.target.name]: e.target.value });
  }

  handleSubmit(event) {
    event.preventDefault();
    this.setState({ isLoading: true });
    this.props.login(this.state).then(function(response) {
    if (response.status == 404){
       return response.json().then(function(val) {
            let myColor = { background: '#f44242', text: "#FFFFFF" };
            notify.show(val.message, "custom", 5000, myColor);
       });
    }else if (response.status == 200){
       return response.json().then(function(val) {
            let myColor = { background: '#3AB54A', text: "#FFFFFF" };
            notify.show("Welcome!", "custom", 5000, myColor);
        })
    }else if (response.status == 422){
       return response.json().then(function(val) {
            let myColor = { background: '#f44242', text: "#FFFFFF" };
            notify.show("The email/password field is required", "custom", 5000, myColor);
        })
    }
    }).catch(function() {
        let myColor = { background: '#f44242', text: "#FFFFFF" };
        notify.show("Error en comunicacion" , "custom", 5000, myColor);
    });

  }

  render() {
    const {email, password, isLoading} = this.state;  
    return (
            <Empty>
                <div className='main'>
                    <Notifications />                    
                </div>
                <h1>Welcome Again</h1>
                <form onSubmit={this.handleSubmit}>
                    <div className="form-group">
                        <label>Email</label>
                        <input type="email" placeholder="email@domain.com" name="email" value={email} className="form-control" onChange={this.onChange}/>
                    </div>
                    <div className="form-group">
                        <label>Password</label>
                        <input type="password" placeholder="***********" name="password" value={password}  className="form-control" onChange={this.onChange} />
                    </div>
                    <div className="form-group form-group-button">                    
                        <button type="submit" className="button button-primary button-right button" style={{width: "100%"}} disabled={isLoading}>LOGIN</button>
                    </div>
                </form>
                <div className="form-description">
                    <Button to='#' classes="button-block button-google">Login using Google+</Button>
                    <Button to='#' classes="button-block button-facebook">Login using Facebook</Button>
                </div>
            </Empty>
    );
  }
}
LoginForm.propTypes = {
    dispatch: PropTypes.func,
    login: PropTypes.func.isRequired
};

export default connect(null, { login })(LoginForm);

The action on the folder actions is:

export function login(data) {
    return dispatch => {
            fetch('MY_URL', {
            method: 'post',
            headers: {
                'Accept': 'application/json, text/plain, */*',
                'Content-Type': 'application/json'
            },
            body: data
        });
    }
}

And the error when the submit trigger:

TypeError: this.props.login(...) is undefined
handleSubmit
src/components/Pages/Login.js:30

  27 | handleSubmit(event) {
  28 |   event.preventDefault();
  29 |   this.setState({ isLoading: true });
> 30 |   this.props.login(this.state).then(function(response) {
  31 |   if (response.status == 404){
  32 |   return response.json().then(function(val) {
  33 |           let myColor = { background: '#f44242', text: "#FFFFFF" };

What am i missing?

Regards.

Ulises
  • 406
  • 7
  • 22

1 Answers1

0

You misused connect with the second argument: http://redux.js.org/docs/basics/UsageWithReact.html#implementing-container-components

You should have done this way

const mapDispatchToProps = dispatch => {
  return {
    login: data => dispatch(login(data)),
  }
}


export default connect(null, mapDispatchToProps)(LoginForm);
yuantonito
  • 1,274
  • 8
  • 17
  • Like this? `LoginForm.propTypes = { dispatch: PropTypes.func, login: PropTypes.func.isRequired }; const mapDispatchToProps = dispatch => { return { login: data => dispatch(login(data)), } } export default connect(null, mapDispatchToProps)(LoginForm);` – Ulises Oct 31 '17 at 22:17
  • Doesn't work :( `TypeError: this.props.login(...) is undefined handleSubmit src/components/Pages/Login.js:30 27 | handleSubmit(event) { 28 | event.preventDefault(); 29 | this.setState({ isLoading: true }); > 30 | this.props.login(this.state).then(function(response) { 31 | if (response.status == 404){ 32 | return response.json().then(function(val) { 33 | let myColor = { background: '#f44242', text: "#FFFFFF" };` – Ulises Oct 31 '17 at 22:21
  • Can you try adding `console.log(this.props)` in the `handleSubmit` and `render` methods to see the values and if they have the same ? – yuantonito Oct 31 '17 at 22:29
  • Thats the log: [Console](https://s3.amazonaws.com/stackoverflowimages/Captura+de+pantalla+2017-10-31+a+la(s)+4.31.16+p.m..png) [Console](https://s3.amazonaws.com/stackoverflowimages/Captura+de+pantalla+2017-10-31+a+la(s)+4.31.28+p.m..png) – Ulises Oct 31 '17 at 22:33
  • That's good, `this.props.login` exists. Can you just try to call `this.props.login(this.state)` without `then`? (It really is debugging right now to know where is the problem exactly to solve it afterwards) – yuantonito Oct 31 '17 at 22:35
  • O: that works! Why when i try the "then" the error is throwed? It's a promise afert all, did you know? – Ulises Oct 31 '17 at 22:38
  • I believe because in your `login` function in the `actions.js`, you don't return anything :) Glad it helped you ! – yuantonito Oct 31 '17 at 22:40
  • did you know a way to catch the response and make the validations on the component? – Ulises Oct 31 '17 at 22:55
  • You can check one of my [answer](https://stackoverflow.com/questions/46974280/conditional-async-actions-in-componentdidmount-lifecycle-method-keeps-going-on-a/46976568#46976568) in another question where I explain the `isFetching` and `didInvalidate` concepts. In the code you can see some error handling with `ADD_CONTACT_ERROR` for example. Basically you catch the error in the `action` and add the error in your reducer and display it if there is one in the component. – yuantonito Oct 31 '17 at 23:02