React Redux: action gets fired but reducer code is not executed

Viewed 56

I'm stuck on writing my first react/redux app. As a user I want to add a star to my favorite item via click on the star. After that, the starcount should update. I displayed all the items with map() and use a Card Component to display them. I can see in the redux tools that my action gets fired when I click on an item and it even gets the right payload (the id of the item I clicked on). But the code I got in my reducer does not get executed (I tried with a simple console.log as well as with more complex code). I cannot figure out where I missed something.

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import rootReducer from './reducers';

const store = createStore(rootReducer, window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__());

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Provider store={store}>
      <App />  
    </Provider>
    
);

App.js

import Card from './Components/Card.js';
import './App.css';
import { useSelector, useDispatch } from 'react-redux';
import * as actions from './actions';

function App() {
  const burgers = useSelector(state => state.burgers);
  const dispatch = useDispatch();

  return (
    <div className="App">
      <div className="App-header">
      </div>

     <div style={{display: 'flex', flexDirection: 'column'}}>
       {burgers.map((item) => 
        <Card img={item.image} title={item.name} price={item.price} stars={item.stars} key={item.name} id={item.id}/>
      )}
      </div>
    </div>
  );
  
}

export default App;

Card.js

import './card.css'
import { BsFillStarFill } from "react-icons/bs";
import { useSelector, useDispatch } from 'react-redux';
import * as actions from './actions';

export default function Card(props) {
    const { title, price, stars, img, id } = props;
    const dispatch = useDispatch();
    const handleClick = event => {
        dispatch(actions.addStar(event.currentTarget.id));
      };
    return (<div className="card">
        <div className="card-header">
            
        </div>
        <div className="card-body">
            <div className="card-title">{title}</div>
            <div className="price">Price: ${price}</div>
            <div className="rating" id={id} onClick={handleClick}>
                <div className="star">
                    <BsFillStarFill />
                </div>
                <div className="count">
                    {stars}
                </div>
                
                
            </div>
            
        </div> 
            
        
    </div>)
}

actions.js

import * as actions from './actionTypes.js'
    
export function addStar(id) {
    return {
        type: actions.ADD_STAR,
        payload: {
            id: id
        }
    }
}

reducers/index.js

import { combineReducers } from 'redux';
import { sortBurgers, updateStarCount } from './sortBurgers.js';

const rootReducer = combineReducers({
    starCount: updateStarCount,
    burgers: sortBurgers
})

export default rootReducer;

sortBurgers.js (my reducer)

export const burgers = [
        {
            id: 1,
            image: hamburger,
            name: "Hamburger",
            price: 1.25,
            stars: 0
        },
        {
            id: 2,
            image: baconBurger,
            name: "Bacon Burger",
            price: 2.50,
            stars: 0
        },
        {
            id: 3,
            image: doubleMeatBurger,
            name: "Double Meat Burger",
            price: 3.75,
            stars: 0
        },
        {
            id: 4,
            image: doubleCheeseBurger,
            name: "Double Cheese Burger",
            price: 5.00,
            stars: 0
        }
    ]
  
    export const updateStarCount = (state = burgers, action) => {
        switch(action.type) {
            case action.ADD_STAR:  
            console.log(action.payload.id);
            let starcount = state.map((item) => {
                return item.id
            } );
            let starIndex = starcount.indexOf(action.payload.id);
            console.log(starIndex);
                return [...state.slice(0, starIndex), state[starIndex].stars + 1, ...state.slice(starIndex + 1)]
            default:
                return state
        }
    }

ActionTypes.js

export const ADD_STAR = "ADD_STAR";
export const TEST = "TEST";
export const INCREMENT = "INCREMENT";
export const DECREMENT = "DECREMENT";
1 Answers

Look at this: sortBurgers.js action.ADD_STAR

actions.js actions.ADD_STAR

different s

You must import the value of actions.ADD_STR from the actions.js and add this value to swith. In your code, the value is action.type is checked against the value of action.ADD_STAR, which is most likely undefined

UPD:

  1. in card.js - event.currentTarget.id is a string. Change in actions.js

    export function addStar(id) {
         return {
             type: actions.ADD_STAR,
             payload: {
               id: Number(id)
             }
         }
     }
  2. replace 'add_star':

    
         case actions.ADD_STAR:
               return state.map((burger) => {
                   if (burger.id === action.payload.id) burger.stars++;
                   return burger;
               })
     
     
Related