React Redux : Action creator not calling reducer
Asked Answered
P

3

14

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);
Parnell answered 12/3, 2017 at 2:24 Comment(1)
you need to dispatch it instead of just call itPhio
B
21

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.

Bosquet answered 12/3, 2017 at 2:32 Comment(6)
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.Parnell
Edited my answer.Bosquet
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 =)Parnell
If my post helped you, feel free to mark it as an answer :-)Bosquet
Nice explanation from @alekkowalczykCabbala
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());Wheen
C
1

There is an often forgotten rule in Redux that when you change the reducer you need to restart your localhost server.

You are doing it correctly- there are many ways to architect Redux into React. You don't need to use mapDispatchToProps if you are importing your action creators using connect()().

Just restart your localhost server if you don't see any typos. (I usually use NPM, so I control+c out of npm start in the terminal and run npm start again each time I add a new reducer.)

Curtis answered 31/10, 2020 at 7:35 Comment(1)
Sometimes the simplest answers are the most complicated to figure out, thanks.Chancre
H
0

I think you might need to show how you're importing other files. My observations from what you shared:

1) You need to import SELECTED_FOOD from types.

2) Your return state should be within the context of the switch statement.

Higgledypiggledy answered 12/3, 2017 at 2:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.