React Redux : Action creator not calling reducer

18,289

The action creator does not call the reducer. It is what it is, nothing more, it creates an action - that is, an object with the action type and the payload for that action.

You need to dispatch an action, to force redux to call the reducer, and that is the place where you use your action creator, that is:

import { Dispatch } from "redux";
import { selectedFood } from "./actions";
Dispatch(selectedFood({type:"hamburger"}));

that should call the reducer, however mostly you'll not call the Dispatch directly, rather in your mapDispatchToProps method used to connect your react component to the redux store.

There are plenty of sample how to use react-redux to use above map functionality, so I would suggest to read into it, and to read how redux works.

====== EDIT after question updated =========

So firstly dispatch from import is not used and ESLint is right telling it, you don't need that import since in:

const mapDispatchToProps = (dispatch) => {
  console.log('IN mapDispatchToProps')
  return {
    onClick: ({data}) => {
      dispatch(selectedFood({data}))
    }
  }
}

you don't call dispatch from your import only from the argument, it's passed to your mapDispatchToProps by the connect function.

Then this is just plain wrong:

<tr onClick={() => selectedFood({data})}>

you imported an action creator which is called on click of table row, that is an action definition is created by the action creator, and that's it. Your code does exactly what you wrote.

The mapDispatchToProps function does what the name suggests - it maps dispatch functions to props of your component.

So it should be:

<tr onClick={() => this.props.onClick({data})}>

and that should dispatch the action and work.

However I would strongly suggest to take some courses or read more about react, redux and react-redux, because your code samples and the question itself suggest, that you are just trying to get something to work, without the basic understanding how it works, and even how javascript works. Sorry for that comment but that's how it looks like.

Share:
18,289
kennedy
Author by

kennedy

Updated on June 05, 2022

Comments

  • kennedy
    kennedy almost 2 years

    My action creator is not calling my reducer. Any help will be much appreciated.

    types.js

    export const SELECTED_FOOD = 'selected_food';
    

    index.js (action creator / action)

    import {
      SELECTED_FOOD
    } from './types';
    
    export function selectedFood({data}) {
    console.log('SELECTED_FOOD **********************',data);
      return({
        type: SELECTED_FOOD,
        payload: data
      });
    }
    

    Output from console.log in action creator

    Object {_id: "18240", description: "Croissants, apple", score: 0.75, fields: Object}
    

    selected_food_reducer.js

    import {
    SELECTED_FOOD
    
    } from '../actions/types';
    
    export default function(state = [], action) {
     switch(action.type) {
      case SELECTED_FOOD:
        console.log('Selected Food Reducer *************', state);
        return  action.payload ;
    }
    
    return state;
    }
    

    EDIT component failing to call dispatch.

    I should have added this on my initial post, it appears there is something wrong in how dispatch is called. ESLint is flagging dispatch on line 3 for defined but never used.

    import React from 'react';
    import { connect } from 'react-redux';
    import { dispatch } from 'react-redux';
    import { selectedFood } from '../actions/index';
    
    class TableRow extends React.Component {
      render() {
        const {
          data
        } = this.props;
    
    
        console.log('PROPS TableRow', this.props);
    
        const row = data.map((data) =>
        <tr onClick={() => selectedFood({data})}>
          <td key={data.description}>{data.description}</td>
          <td key={data.id}>{data.fields.nutrients[0].amountPer100G}</td>
          <td key={data.id}>{data.fields.nutrients[1].amountPer100G}</td>
          <td key={data.id}>{data.fields.nutrients[4].amountPer100G}</td>
        </tr>
        );
        return (
          <tbody>{row}</tbody>
        );
      }
    }
    
    const  mapStateToProps = (state) => {
      return {
        selectedFood: state.selectedFood
      }
    }
    
    
    const mapDispatchToProps = (dispatch) => {
      console.log('IN mapDispatchToProps')
      return {
        onClick: ({data}) => {
          dispatch(selectedFood({data}))
        }
      }
    }
    
    export default connect(mapStateToProps, mapDispatchToProp)(TableRow);
    
  • kennedy
    kennedy about 7 years
    Thank you Alek, I was not importing dispatch originally, but after doing so, it still does work and ESLint is flagging it for being declared but never used. I believe there is something incorrect in mapDispatchToProps, but I am failing to see it.
  • alek kowalczyk
    alek kowalczyk about 7 years
    Edited my answer.
  • kennedy
    kennedy about 7 years
    Thank you Alek, thats good advice. I went through and read the redux documentation again last night and found the issue. It helped clear up a lot. I was going to update my post. Thanks again for your help =)
  • alek kowalczyk
    alek kowalczyk about 7 years
    If my post helped you, feel free to mark it as an answer :-)
  • Sathish Sundharam
    Sathish Sundharam over 5 years
    Nice explanation from @alekkowalczyk
  • Brady Dowling
    Brady Dowling almost 5 years
    This was exactly it for me. I was calling the action from somewhere outside of a React component so I had to call dispatch directly on that action call and then it worked: ReduxStore.dispatch(myaction());