简体   繁体   中英

Uncaught TypeError: this.props.dispatch is not a function

I am trying to dispatch an action when I submit a form but I'm getting this:

Uncaught TypeError: this.props.dispatch is not a function

This is my class:

/**
 *
 * CatalogPage
 *
 */

import React from 'react';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { compose } from 'redux';
import { Form, Control } from 'react-redux-form/immutable';

import injectSaga from 'utils/injectSaga';
import injectReducer from 'utils/injectReducer';
import makeSelectCatalogPage from './selectors';
import reducer from './reducer';
import saga from './saga';

export class CatalogPage extends React.Component { // eslint-disable-line react/prefer-stateless-function

  handleSubmit = (user) => {
    this.props.dispatch({ type: 'test action' });
  }

  render() {
    return (
      <Form
        model="user"
        onSubmit={(user) => this.handleSubmit(user)}
      >
        <label htmlFor=".firstName">First name:</label>
        <Control.text model=".firstName" id=".firstName"/>

        <label htmlFor=".lastName">Last name:</label>
        <Control.text model=".lastName" id=".lastName"/>

        <button type="submit">
          Finish registration!
        </button>
      </Form>
    );
  }
}

CatalogPage.propTypes = {};

const mapStateToProps = createStructuredSelector({
  catalogpage: makeSelectCatalogPage(),
});

function mapDispatchToProps(dispatch) {
  return {
    dispatch,
  };
}

const withConnect = connect(mapStateToProps, mapDispatchToProps);

const withReducer = injectReducer({ key: 'catalogPage', reducer });
const withSaga = injectSaga({ key: 'catalogPage', saga });

export default compose(
  withReducer,
  withSaga,
  withConnect,
)(CatalogPage);

I thought that the compose function at the bottom would connect my component to the store and thus have access to the dispatch function through this.props.dispatch. But it's not working, what am I missing?

Thanks!

EDIT: I've changed handleSubmit to arrow function but problem still persists

handleSubmit = (user) => {
    this.props.dispatch({ type: 'test action' });
  }

EDIT: The problem resolved itself

Something to mention is that react-boiler-plate is not as user-friendly as one might expect. There's alot of weird things that are happening and took me a long time to debug.

The problem here is the misunderstanding of a class method and the way that React manages instances.

You can do three things to avoid this problem:

1) Convert the (handleSubmit) function to an arrow function so in that case, it won't have its own this .

handleSubmit = (user) => { // ...logic here }

2) Create a constructor inside the component and do the next step:

this.handleSubmit = this.handleSubmit.bind(this)

In this case, you attach this to the function each time an instance is created.

3) When you call the method inside the render use the .bind() to bind this :

onSubmit={(user) => this.handleSubmit.bind(this, user)}

You don't need mapDispatchToProps if you just want to inject dispatch into your component. You would use that when you want to bind your action creators before injecting them into your component. Just pass mapStateToProps with no second param and you should be good.

You also need to do what Jose Gomez suggests below. Basically you need to bind this. The easiest way is to just change handleSubmit to an arrow function

handleSubmit = user => {
...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM