The problem is that when I call the dispatch function of the useReducer hook declared in the Context SelectedMealContext
, the<Item/>
gets re-evaluated even if I am not changing the state of useReducer in the context.
My <MealLists/>
component has array of objects and renders <Item/>
by map() from mealsData .
The component tree is <MealLists/>
> <Item/>
> <ItemAmount/>
> <Input/>
Only the <Item/>
has called the Context as useContext(SelectedMealContext)
Note : <Input/>
component is export default React.memo(Input)
thats why it is re-evaluated only when <App/>
loads .
When the app loads first the all of logged messages get shown ,Now on first click of Add button I get the re-evaluated messages again but after the first click and so on I don't get further re-evaluation as shown below in images:
The Console is cleared after App loaded and each call of dispatch function by click Add button **
When app loads :
**
At first click :
**
**
At second click :
**
import Item from './item';
import Card from '../UI/card'
import styles from './mealists.module.css'
const mealsData = [
{
id: 'm1',
name: 'Sushi',
description: 'Finest fish and veggies',
price: 22.99,
},
{
id: 'm2',
name: 'Schnitzel',
description: 'A german specialty!',
price: 16.5,
},
{
id: 'm3',
name: 'Barbecue Burger',
description: 'American, raw, meaty',
price: 12.99,
},
{
id: 'm4',
name: 'Green Bowl',
description: 'Healthy...and green...',
price: 18.99,
},
]
const MealLists =()=>{
console.log("Meals Lists components");
return (
<>
<Card card={styles.meal} style={{marginTop: '200px'}}>
<ul >
{mealsData.map((mealItem)=>{
return <Item
key={mealItem.id}
id={mealItem.id}
mealName={mealItem.name}
mealDescription={mealItem.description}
mealPrice={mealItem.price}/>
})}
</ul>
</Card>
</>
)
}
export default MealLists;
My Context SelectedContext is as :
import React,{useReducer} from 'react'
export const SelectedMealContext = React.createContext();
const SelectedDishesReducer =(state,action)=>{
if(action.type ==='increment'){
console.log("Increment")
}else if(action.type === 'decrement'){
console.log("Decrement")
}else if(action.type === "new_meal"){
console.log("New Meal")
console.log(action.data)
}
}
const SelectedDishes = []
const SelectedMealContextProvider= (props) => {
console.log("Selected Meals Context evaluated");
const [SelectedMeals , dispatchAction ] = useReducer(SelectedDishesReducer,SelectedDishes);
console.log(SelectedMeals);
return (
<SelectedMealContext.Provider
value={{
SelectedMeals : SelectedMeals,
onIncrement : dispatchAction,
onDecrement : dispatchAction,
onAdd : dispatchAction
}}
>{props.children}
</SelectedMealContext.Provider>
)
}
export default SelectedMealContextProvider ;
and the subscriber component is <Item/>
import React ,{useContext} from 'react'
import styles from './item.module.css'
import ItemAmount from './ItemAmount'
import {SelectedMealContext} from '../DataContext/SelectedContext'
const Item =(props )=>{
console.log(`Item component for : ${props.id}`)
const Add = useContext(SelectedMealContext).onAdd;
const AddSelectedItems =(amount)=>{
console.table(props.id , props.mealName ,props.mealPrice)
let selectedDish = {
mealId: props.id,
mealName: props.mealName,
price: props.mealPrice,
number_of_meal : amount}
Add({type: "new_meal",data: selectedDish})
// console.log(`SelectedDish : ${selectedDish.number_of_meal}`)
}
return(
<li key={props.id} className={styles.meal}>
<div>
<h1 className={styles.mealName}>{props.mealName}</h1>
<h3 className={styles.description}>{props.mealDescription}</h3>
<h2 className={styles.price}>{props.mealPrice}</h2>
</div>
<ItemAmount AddSelectedItems={AddSelectedItems}/>
</li>
)
}
export default Item ;