Gonzalo Ortellado
Gonzalo Ortellado

Reputation: 583

React Redux - How to dispatch an action on componentDidMount when using mapDispatchToProps in a connected component

I'm having problems with this. I'm creating a small app with react redux.

In the code below is my app.js component. It was working fine until I tried to use the mapDispatchToProps function inside connect. The problem is that I cannot invoke the dispatch action on componentDidMount anymore. The actions that were in componentDidMount and that now are on mapStateToProps need to be called on comoponentDidMount. Any clues in how to do that?

import React, { Component } from 'react';
import './App.css';
import '../../node_modules/bootstrap/less/bootstrap.less';
import { Route } from 'react-router-dom'
import * as ReadableAPI from '../ReadableAPI'
import HeaderNavigation from './HeaderNavigation';
import TableBody from './TableBody';
import { connect } from 'react-redux';
import sortAsc from 'sort-asc';
import sortDesc from 'sort-desc';
import {
  selectedCategory,
  fetchCategoriesIfNeeded,
  fetchPostsIfNeeded,
  invalidateSubreddit,
  orderPost
} from '../actions'

class App extends Component {

		state = {
			posts: []
		}

		componentDidMount() {
			const { dispatch, selectedCategory, fetchCategories, fetchPosts} = this.props
    		//dispatch(fetchCategoriesIfNeeded(selectedCategory))
    		//dispatch(fetchPostsIfNeeded(selectedCategory))
		}

		orderByScoreAsc = (posts) => {

	      return posts.sort(sortAsc('voteScore'))

	    }

	  	orderByScoreDesc = (posts) => {

	      return posts.sort(sortDesc('voteScore'))

	    }

	  	render() {

	  	const { navCategories, posts } = this.props

	    return (
	      <div>
	        <HeaderNavigation navCategories = {navCategories} />

	        <Route exact path="/" render={()=>(
	          <TableBody 
	          	showingPosts={posts} 
	          />)}
	        />

	        
	        
	      </div>
	    );
	  }
}

function mapStateToProps ( state ) {
  const { categories, posts } = state
  return {
     navCategories: categories.items,
     posts: posts.items
  }
}

function mapDispatchToProps (dispatch) {
  return {
    changeOrder: (data) => dispatch(orderPost(data)),
    fetchCategories: (data) => dispatch(fetchCategoriesIfNeeded(data)),
    fetchPosts: (data) => dispatch(fetchPostsIfNeeded(data))
  }
}


export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App)

Upvotes: 9

Views: 28183

Answers (3)

Tomasz Mularczyk
Tomasz Mularczyk

Reputation: 36179

I modified your code to what I think will work. I also left comments.

class App extends Component {

  state = {
    posts: []
  }

  componentDidMount() {
    // no need to use dispatch again. Your action creators are already bound by 
    // mapDispatchToProps.  Notice also that they come from props
    const { selectedCategory, fetchCategoriesIfNeeded, fetchPostsIfNeeded} = this.props;
    fetchCategoriesIfNeeded(selectedCategory);
    fetchPostsIfNeeded(selectedCategory);
  }

  //... the same
}

function mapStateToProps ( state ) {
  //... the same
}

function mapDispatchToProps (dispatch) {
  // when arguments match, you can pass configuration object, which will 
  // wrap your actions creators with dispatch automatically.
  return {
    orderPost,
    fetchCategoriesIfNeeded,
    fetchPostsIfNeeded,
  }
}

Upvotes: 9

jenriquer
jenriquer

Reputation: 166

You just don't. The mapDispatchToProps does exactly what you are trying to do in your component. Instead of calling a dispatch you call the method that was provided to your component by connect. in your case:

componentDidMount() {
    const { selectedCategory, fetchCategories, fetchPosts} = this.props;
    fetchCategories(selectedCategory);
    fetchPosts(selectedCategory);
}

Upvotes: 1

Dream_Cap
Dream_Cap

Reputation: 2302

In map to dispatch you have fetchCategories/fetchPosts so therefore you need to call them like this:

componentDidMount() {

            const { dispatch, selectedCategory, fetchCategories, fetchPosts } = this.props
            //Call like this instead of fetchCategoriesIfNeeded/fetchPostsIfneeded
            //dispatch(fetchCategories(selectedCategory))
            //dispatch(fetchPosts(selectedCategory))
        }

You have this:

function mapDispatchToProps (dispatch) {
  return {
    changeOrder: (data) => dispatch(orderPost(data)),
    fetchCategories: (data) => dispatch(fetchCategoriesIfNeeded(data)),
    fetchPosts: (data) => dispatch(fetchPostsIfNeeded(data))
  }
}

So you need to call fetchCategories/fetchPosts from your props instead of fetchCatIfneeded/fetchPostsifneeded

Upvotes: 5

Related Questions