I am working on a shopping basket component in React Native. The content and price of the basket get saved in the global redux store. When the user selects an item, an action gets dispatched to add the item to the basket and to update the total basket price.
The UI however does not get updated on this global state change.
My Reducer
const INITIAL_STATE = {
basket: [],
basketPrice: 0,
};
const mainReducer = (state = INITIAL_STATE, action) => {
const stateCpy = state;
switch (action.type) {
case 'SET_BASKET':
stateCpy.basket = action.payload
return stateCpy;
case 'ADD_TO_BASKET':
stateCpy.basket.push(action.payload)
return stateCpy
case 'REMOVE_FROM_BASKET':
let tempItems = stateCpy.basket
for (var x = 0; x < stateCpy.basket.length; x++) {
if (stateCpy.basket[x]._id === action.payload) {
tempItems.splice(x, 1)
break;
}
}
stateCpy.basket = tempItems
return stateCpy
case 'SET_BASKET_PRICE':
stateCpy.basketPrice = action.payload
console.log(stateCpy.basketPrice)
return stateCpy
default:
return state
}
};
export default mainReducer
My Actions
const setBasket = basket => ({
type: 'SET_BASKET',
payload: basket,
});
const addToBasket = item => ({
type: 'ADD_TO_BASKET',
payload: item,
});
const removeFromBasket = item_id => ({
type: 'REMOVE_FROM_BASKET',
payload: item_id,
});
const setBasketPrice = price => ({
type: 'SET_BASKET_PRICE',
payload: price,
});
export default actions = {
setBasket,
addToBasket,
removeFromBasket,
setBasketPrice
}
My UI Component
...
import { useSelector, useDispatch } from 'react-redux'
export const RestaurantView = ({ navigation, route }) => {
const basket = useSelector((state) => state.basket)
const basketPrice = useSelector((state) => state.basketPrice)
const dispatch = useDispatch()
...
function calcBasketPrice(){
let tempBasketPrice = 0
basket.forEach(element => {
tempBasketPrice += element.price
});
return tempBasketPrice
}
function addToBasket(item) {
dispatch(actions.setBasketPrice(calcBasketPrice() + item.price))
dispatch(actions.addToBasket(item))
}
return ( <View>
<ItemCard onPress={addToBasket}> </ItemCard>
<Text style={{ textAlign: "right", padding: 15, fontSize: 20 }}> {basketPrice}</Text>
</View>)
}
When logging the basketPrice to console in the reducer, it logs the correct, updated value on each press/dispatch but there no changes in the UI. When a local state change is made to force a rerender, it renders with the correct value from the global store.