Doe
Doe

Reputation: 163

Dispatch is not a function react

I'm working on an application using react and redux. I use api.

application flow:

The first component is the form to which you enter information (name, calories, type of diet).

    class FormPage extends Component {
      constructor(props) {
        super(props);

        this.handleFormSubmit = this.handleFormSubmit.bind(this);
        this.goToListOfMealPage = this.goToListOfMealPage.bind(this);
      }

      handleFormSubmit(data) {
        const name = data.name;
        const calories = data.caloreis;
        const diet = data.diet;
        const health = data.health;

        console.log(name)
        return loadData( name, calories, diet, health)()
          .then(({ error }) => {
            if (!error) {
              setTimeout(this.goToListOfMealPage, 1500);
            }

            return error;
          }
        );
      }

      goToListOfMealPage() {
        const { history } = this.props;
        history.push('/ListMeal');
      }

      render() {
        return (
          <Form onSubmit={this.handleFormSubmit}/>
        );
      }
    }

const mapDispatchToProps = (dispatch) => {
  return {
    loadData: () => dispatch(loadData())
  }
};

FormPage = connect(mapDispatchToProps)(FormPage)
export default FormPage;

handleFromSubmit function is to send form data to the api link (https://api.edamam.com/search?q=${name}n&app_id=${key.id}&app_key=${key.key}&calories=${calories}&health=${health}&diet=${diet}).

After filling in the form and after clicking the send button, I want to have a list of meals (recipes) on the new subpage.

where loadData is

const fetchDataStart = () => ({
  type: actionTypes.FETCH_DATA_START,
});

const fetchDataSucces = (data) => ({
  type: actionTypes.FETCH_DATA_SUCCESS,
  data,
});

const fetchDataFail = () => ({
  type: actionTypes.FETCH_DATA_FAIL,
});

const loadData = (name, calories, diet, health) => (dispatch) => {
  dispatch(fetchDataStart());
  return axios.get(`https://api.edamam.com/search?q=${name}n&app_id=${key.id}&app_key=${key.key}&calories=${calories}&health=${health}&diet=${diet}`)
    .then(({ data }) => console.log(data) || dispatch(fetchDataSucces(data)))
    .catch((err) => dispatch(fetchDataFail(err.response.data)));
};

After sending the form, I get an error TypeError: dispatch is not a function

enter image description here

I can not find the reason for this error

Upvotes: 0

Views: 789

Answers (2)

Brian Le
Brian Le

Reputation: 2686

There are some problems with your code:

  • If you have mapped the dispatch to prop, you can invoke the action by doing this.props.loadData(params)
  • You should not invoke the action by doing this loadData()() as the dispatched action does not return a function (don't let it trick you although the original action returns a function).

So, to use loadData() action, you need to map it to props like so:

const mapDispatchToProps = dispatch => ({
  loadData: (name, calories, diet, health) => dispatch(loadData(name, calories, diet, health)),
});

Then use it like so:

componentDidMount() {
  this.props.loadData(name, calories, diet, health)
    .then(() => console.log('Success'))
    .catch(err => throw new Error("Error", err.stack))
}

Edit: Based on your newly edited question, the connect function in redux accepts mapStateToProps and mapDispatchToProps respectively, so in your code it should be:

export default connect(null, mapDispatchToProps)(Component)

Upvotes: 5

Avanthika
Avanthika

Reputation: 4182

  1. Your constructor is not needed - you can auto-bind the functions this way.

  2. If there's no mapStateToProps in the component, maintain it as null.

EDITED CODE:

import React from 'react';
// Your imports

class FormPage extends Component {
  handleFormSubmit = (data) => {
    const { name, caloreis, diet, health } = data;
    this.props.loadData(name, caloreis, diet, health);
  }

  goToListOfMealPage = () => {
    const { history } = this.props;
    history.push('/ListMeal');
  }

  render() {
    return (
      <Form onSubmit={this.handleFormSubmit} />
    );
  }
}

const mapDispatchToProps = dispatch => ({
  loadData: (name, caloreis, diet, health) => dispatch(loadData(name, caloreis, diet, health))
});

export default connect(null, mapDispatchToProps)(FormPage);

Suggestion on redirect:

  1. You have to maintain success and error of submit in redux state, if success - you can redirect to goToListOfMealPage - You can do this in componentWillReceiveProps. We should do something similar to the below code:
class FormPage extends Component {
  componentWillReceiveProps(nextProps) {
    if (this.props.formSubmitSuccess !== nextProps.formSubmitSuccess && nextProps.formSubmitSuccess) {
      this.goToListOfMealPage()
    }
  }
  //... rest of the code.
}

// Your map state to props:
const mapStateToProps = state => ({
  formSubmitSuccess: state.reducerIdentifier.formSubmitSuccess,
  formSubmitFailure: state.reducerIdentifier.formSubmitFailure
});

Upvotes: 1

Related Questions