Reputation: 127
I stuck in this moment creating store with different products, that I want to add to the basket. The problem occur when I wanted to pass the state of cardList into Basket component to change the information from "Basket is empty" to display information how many items are currently in basket.
Below I paste my main hooks component with basket component which include all functionality.
Basket component:
import React from 'react'
const Basket = (props) => {
return (
<div>
{props.cardItems.length === 0 ? "Basket is empty" : <div> You have {props.cardItems.length} products in basket!</div>}
</div>
)
}
export default Basket;
Main component:
function
const [cardItems, setCardItems] = useState([]);
const price = 2.50;
useEffect(() => {
fetch(URL, {
method: 'GET',
headers: {
Accept: "application/json",
}
}).then(res => res.json())
.then(json => (setBeers(json), setFilteredBeers(json))
);
}, [])
function handleMatches(toMatch) {...
}
const displayFilterBeers = event => {...
}
const handleRemoveCard = () => {...
}
const handleAddToBasket = (event, beer) => {
setCardItems(state => {
let beerAlreadyInBasket = false;
cardItems.forEach(item => {
if (item.id === beer.id) {
beerAlreadyInBasket = true;
item.count++;
};
});
if (!beerAlreadyInBasket) {
cardItems.push({ ...beer, count: 1 })
}
localStorage.setItem('baketItems', JSON.stringify(cardItems));
console.log('cardItems: ', cardItems, cardItems.length);
return cardItems;
})
}
return (
<div className="App">
<div className='search'>
<input type='text' placeholder='search beer...' onChange={displayFilterBeers} />
</div>
<BeerList BeersList={filteredBeers} price={price} handleAddToBasket={handleAddToBasket} />
<Basket cardItems={cardItems}/>
</div>
);
}
export default App;
I saw an example that without React hooks that in basket component someone used const {cartItems} = this.props; but I don't know how to achieve something similar using hooks.
Upvotes: 2
Views: 8686
Reputation: 619
I think what you are facing is related to this issue.
So when dealing with array or list as state, react doesn't re-render if you don't set state value to a new instance. It assumes from the high-level comparison that the state hasn't been changed. So it bails out from the re-rendering.
from the issue I found this solution is better than the others -
const handleAddToBasket = (event, beer) => {
const nextState = [...cardItems, beer] // this will create a new array, thus will ensure a re-render
// do other stuffs
setCardItems(nextState);
};
Upvotes: 4