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";