Reputation: 55
Help, please, to solve a problem. I tried a huge number of solutions, but nothing worked.
My state
class App extends Component {
constructor(props) {
super(props);
this.state = {
countId:{quantityId:[]},
}}
CountId creates an array of objects in state. Id is taken from another component (no problem with this). To demonstrate what is in id, you can take Product 1,Product 2.... and accordingly this.state.countId.quantityId will be {Product 1, quantity: 1}, {Product 2, quantity: 1}
CountId = (event) => {
this.setState({
countId:{
...this.state.countId,
quantityId:
this.state.countId.quantityId.concat({id:(event.currentTarget.id), quantity: 1})}})
}
I am using cloneDeep lodash to create a deep copy of an object.
IncrementItem = () => {
const deepIncrement = cloneDeep(this.state.countId.quantityId);
this.setState({
...this.state.countId.quantityId,
quantity: deepIncrement.map(i => i.id ).quantity + 1
})}
buttons to increase or decrease the quantity and the quantity output itself
<button onClick={this.IncrementItem}>+</button>
<div>{this.state.countId.quantityId.map(c => c.id ? c.quantity: null)}</div>
<button onClick={this.DecrementItem}>-</button>
More code
App.js
class App extends Component {
constructor(props) {
super(props);
this.state = {
id: [],
countId:{quantityId:[]},
};
}
CountId = (event) => {
this.setState({
countId:{
...this.state.countId,
quantityId:
this.state.countId.quantityId.concat({id:(event.currentTarget.id), quantity: 1})}})
}
IncrementItem = (id) => {
const itemFound = this.state.countId.quantityId.find(element => element.id ===id);
if (itemFound) {
this.setState({
...this.state,
countId: {...this.state.countId, quantityId:
[{...itemFound, quantity: itemFound.quantity + 1 },
...this.state.countId.quantityId.filter(element => element.id !==id)]}
})}
}
DecrementItem = (id) => {
const itemFound = this.state.countId.quantityId.find(element => element.id ===id);
if (itemFound) {
this.setState({
...this.state,
countId: {...this.state.countId, quantityId:
[{...itemFound, quantity: itemFound.quantity - 1 },
...this.state.countId.quantityId.filter(element => element.id !==id)]}
})}
}
render() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path='/store' element={<Store CountId={this.CountId}/>}/>
<Route path='/cart' element={<Cart countId={this.state.countId}/>}/>
</Routes>
</BrowserRouter>
</div>
)}
Store
export default class Store extends Component {
constructor(props) {
super(props);
this.state = {
products: [
{
id: "apple"
},
{
id: "lemon"
},
{
id: "melon"
}
]
};
}
countId = () => {
if (this.props.CountId) {
this.props.CountId();
}
};
render() {
return (
<div>
{this.state.products.map((p) => {
return (
<div id={p.id} onClick={this.props.countId }>
CountId
</div>
);
})}
</div>
);
}
}
Cart
export default class Cart extends Component {
constructor(props) {
super(props);
this.state = {
products: [
{
id: "apple"
},
{
id: "lemon"
},
{
id: "melon"
}
]
};
}
render() {
return (
<div>
{this.state.products.map((p) => {
return (
<div>
<button onClick=
{()=>this.props.IncrementItem(id)} >+</button>
<div >
{value.state.countId.quantityId.map(c => c.id ? c.quantity: 1)}</div>
<button onClick=
{this.props.DecrementItem} id={products.id}>-</button>
</div>
);
})}
</div>
);
}
}
Upvotes: 0
Views: 285
Reputation: 244
This is your corrected code as per your ask, but i still feel you must correct the function names to make it more concise and readable.
import { Component } from "react";
import { Routes } from "react-router";
// import Store from "./Store";
// import Cart from "./Cart"
import {
BrowserRouter,
Link,
Route,
} from "react-router-dom";
import Home from "./Home";
class App extends Component {
constructor(props) {
super(props);
this.state = {
id: [],
countId: { quantityId: [] },
};
this.IncrementItem = this.IncrementItem.bind(this);
this.DecrementItem = this.DecrementItem.bind(this)
}
CountId = (event) => {
const id = event.currentTarget.id
this.IncrementItem(id)
}
IncrementItem = (id) => {
const itemFound = this.state.countId.quantityId.find(element => element.id === id);
if (itemFound) {
const indexOfItemFound = this.state.countId.quantityId.indexOf(itemFound)
this.setState({
countId: {
...this.state.countId,
quantityId: [
...this.state.countId.quantityId.slice(0, indexOfItemFound),
{ ...itemFound, quantity: itemFound.quantity + 1 },
...this.state.countId.quantityId.slice(indexOfItemFound + 1),
]
}
})
}
else {
this.setState({
countId: {
...this.state.countId,
quantityId: [
...this.state.countId.quantityId,
{ id: id, quantity: 1 }
]
}
})
}
}
DecrementItem = (id) => {
const itemFound = this.state.countId.quantityId.find(element => element.id === id);
if (itemFound) {
const indexOfItemFound = this.state.countId.quantityId.indexOf(itemFound)
if (itemFound.quantity > 1) {
this.setState({
countId: {
...this.state.countId,
quantityId: [
...this.state.countId.quantityId.slice(0, indexOfItemFound),
{ ...itemFound, quantity: itemFound.quantity - 1 },
...this.state.countId.quantityId.slice(indexOfItemFound + 1),
]
}
})
}
else {
this.setState({
countId: {
...this.state.countId,
quantityId: [
...this.state.countId.quantityId.filter(element => element.id !== id)
]
}
})
}
}
}
render() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path='/store' element={<Store CountId={this.CountId} />} />
<Route path='/cart' element={<Cart countId={this.state.countId} IncrementItem={this.IncrementItem} DecrementItem={this.DecrementItem} />} />
</Routes>
</BrowserRouter>
</div>
)
}
}
export default App;
class Store extends Component {
constructor(props) {
super(props);
this.state = {
products: [
{
id: "apple"
},
{
id: "lemon"
},
{
id: "melon"
}
]
};
}
render() {
return (
<div>
<Link to="/cart">Goto cart</Link>
{this.state.products.map((p) => {
return (
<div id={p.id} onClick={this.props.CountId}>
CountId - {p.id} - Click on me
</div>
);
})}
</div>
);
}
}
class Cart extends Component {
render() {
return (
<div>
{this.props.countId.quantityId.map((item) => {
return (
<div>
<button onClick={() => this.props.IncrementItem(item.id)}>+</button>
<div >
{`Item is ${item.id} with quantity ${item.quantity}`}
</div>
<button onClick={() => this.props.DecrementItem(item.id)}>-</button>
</div>
);
})}
</div>
);
}
}
Upvotes: 1
Reputation: 244
Something is wrong here.
IncrementItem = () => {
const deepIncrement = cloneDeep(this.state.countId.quantityId);
this.setState({
...this.state.countId.quantityId,
quantity: deepIncrement.map(i => i.id ).quantity + 1
})}
May be you can try this.
IncrementItem = (id) => {
const itemFound = this.state.countId.quantityId.find(element => element.id ===id);
if (itemFound) {
this.setState({
...this.state,
countId: {…this.state.countId, quantityId: [{…itemFound, itemFound.quantity +1 }, …this.state.countId.quantityId.filter(element => element.id !==id)]}
})}
}
App.js
import { Component } from "react";
import { Routes } from "react-router";
import Store from "./Store";
import Cart from "./Cart"
import {
BrowserRouter,
Route,
} from "react-router-dom";
import Home from "./Home";
const products = [
{
id: 1,
name: "Apple"
},
{
id: 2,
name: "Lemon"
},
{
id: 3,
name: "Melon"
}
]
class App extends Component {
constructor(props) {
super(props);
this.state = {
products: [...products],
cartItems: [],
};
this.addToCart = this.addToCart.bind(this);
this.removeFromCart = this.removeFromCart.bind(this);
}
addToCart(id) {
const foundItem = this.state.cartItems.find(item => item.id === id);
if (foundItem) {
const indexOfFoundItem = this.state.cartItems.indexOf(foundItem)
this.setState({
...this.state,
cartItems: [
...this.state.cartItems.slice(0, indexOfFoundItem),
{ ...foundItem, quantity: foundItem.quantity + 1 },
...this.state.cartItems.slice(indexOfFoundItem + 1)
]
})
} else {
this.setState({
...this.state,
cartItems: [
...this.state.cartItems,
{ ...this.state.products.find(product => product.id === id), quantity: 1 }
]
})
}
}
removeFromCart(id) {
const foundItem = this.state.cartItems.find(item => item.id === id);
if (foundItem) {
const indexOfFoundItem = this.state.cartItems.indexOf(foundItem)
if (foundItem.quantity > 1) {
this.setState({
...this.state,
cartItems: [
...this.state.cartItems.slice(0, indexOfFoundItem),
{ ...foundItem, quantity: foundItem.quantity - 1 },
...this.state.cartItems.slice(indexOfFoundItem + 1)
]
})
} else {
this.setState({
...this.state,
cartItems: [
...this.state.cartItems.filter(item => item.id !== id)
]
})
}
}
}
render() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path='/store' element={
<Store
products={this.state.products}
addToCart={this.addToCart}
/>
}
/>
<Route path='/cart' element={
<Cart
cartItems={this.state.cartItems}
addToCart={this.addToCart}
removeFromCart={this.removeFromCart}
/>
}
/>
<Route path='/' element={
<Home
products={this.state.products}
cartItems={this.state.cartItems}
addToCart={this.addToCart}
removeFromCart={this.removeFromCart}
/>
}
/>
</Routes>
</BrowserRouter>
</div>
)
}
}
export default App;
Home.js
import { Component } from "react";
import Cart from "./Cart";
import Store from "./Store";
export default class Home extends Component {
render() {
return (
<div>
<h1>Welcome to Store</h1>
<hr />
<div>
Your Cart
<Cart
cartItems={this.props.cartItems}
addToCart={this.props.addToCart}
removeFromCart={this.props.removeFromCart}
/>
<hr />
Available products
<Store
products={this.props.products}
addToCart={this.props.addToCart}
/>
</div>
</div>
);
}
}
Store.js
import { Component } from "react";
import { Link } from "react-router-dom";
export default class Store extends Component {
render() {
return (
<div style={{maxWidth:"600px"}}>
Product List, <Link to={'/cart'}>Click here for cart</Link>, <Link to={'/'}>Home</Link>
<hr />
{this.props.products.map((product, index) => {
return (
<div id={product.id} key={index}>
{`${product.id}. ${product.name}`}
<button onClick={() => this.props.addToCart(product.id)}>Add to cart</button>
</div>
);
})}
</div>
);
}
}
Cart.js
import { Component } from "react";
import { Link } from "react-router-dom";
export default class Cart extends Component {
render() {
return (
<div style={{maxWidth:"600px"}}>
Choosed Items, <Link to={'/store'}>Click here for products</Link>, <Link to={'/'}>Home</Link>
<hr />
{ this.props.cartItems.length === 0 ?
"Nothing is addded to the cart" :
this.props.cartItems.map((item, index) => {
return (
<div id={item.id} key={index} >
{`Product: ${item.name}, Quantity: ${item.quantity}`}
<button onClick={() => this.props.addToCart(item.id)}>Add one</button>
<button onClick={() => this.props.removeFromCart(item.id)}>Remove</button>
</div>
);
})
}
</div>
);
}
}
Let me know if this helps, or if you have any doubts around this. Play with it Here
Upvotes: 1