Do you understand the reason why props.history.push(“/cart/” + props.match.params.id + “?quantity=” + quantity) is not working. It is giving me Cannot read properties of undefined (reading ‘push’)
I am aware I should receive the object history, but I cannot access to it. It says undefined.
ProductScreen
import {Link,useNavigate,useHistory, withRouter,Route} from 'react-router-dom';
import axios from 'axios';
import React,{useState,useEffect,useReducer,Component} from 'react';
import {useParams} from 'react-router-dom';
import logger from 'use-reducer-logger';
{/*import Badge from 'react-bootsrap/Button';
import Rating from '../components/Rating';
import {Helmet} from 'react-helmet-async';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';
import {getError} from '../utils';
import {Store} from '../Store'; */}
const reducer = (state,action) => {
switch(action.type){
case 'FETCH_REQUEST':
return {...state,loading: true};
case 'FETCH_SUCCESS':
return {...state,product: action.payload,loading:false};
case 'FETCH_FAIL':
return {...state,loading:false,error: action.payload};
default:
return state;
}
};
function ProductScreen(props){
const params = useParams();
const {_id} = params;
const [color, setColor] = React.useState(0);
const [size, setSize] = React.useState(0);
const [quantity, setQuantity] = React.useState(0);
let varyOfColor=parseInt(color);
let varyOfSize=parseInt(size);
let varyOfQuantity=parseInt(quantity);
let priceInFunctionOfColorAndSize=varyOfSize+varyOfColor;
const [{loading, error, product},dispatch] = useReducer(logger(reducer),{
product: {},
loading: true,
error: '',
});
useEffect(()=>{
const fetchData = async()=>{
dispatch({type: 'FETCH_REQUEST'});
try{
const result = await axios.get(`/api/products/${_id}`);
dispatch({type: 'FETCH_SUCCESS',payload:result.data})
}catch(err){
dispatch({type: 'FETCH_FAIL', payload: err.message});
}
};
fetchData();
},[_id]);
{/* const {state,dispatch: ctxDispatch} = useContext();
const addToCartHandler = () => {
ctxDispatch({type: 'CART_ADD_ITEM', payload: {...product,quantity:1}})
}*/}
const handleAddToCart = () => {
props.history.push("/cart/" + props.match.params.id + "?quantity=" + quantity);
}
return(
loading?<div>Loading...</div>
:error? <div>{error}</div>
:
<div>
<div>
<div>
{/*<Link to="/">Back to results</Link> */}
<div className="product-report">
<Link to={`/products/${product.name}`}>
<img className="image" src={product.image} alt={product.name} ></img>
</Link>
<div className="product-description">
<div className="name-product">{product.name}</div>
<div className="rating-product">{product.rating}</div>
<div className="product-price-variation">
<div className="product-price">Price:</div>
<div className="variation-price">{"$"+(product.price+priceInFunctionOfColorAndSize)*varyOfQuantity}</div>
</div>
<div className="product-size-variation">
<div className="product-size">Size:</div>
<div className="size-variation">
<select className="size-select-button" value={size} onChange={(event) => {setSize(event.target.value);}}>
{
product.size && Array.isArray(product.size) ? (
product.size.map((item, i) => (
<option key={i} value={i}>
{item}
</option>
))
) : (
<option value="">No sizes available</option>
)
}
</select>
{/*<p>
<strong>Current value:</strong>
{size}
</p>*/}
</div>
</div>
<div className="product-color-variation">
<div className="color-product">Color:</div>
<div className="color-variation">
<select className="color-select-button" value={color} onChange={(event) => {setColor(event.target.value);}}>
{
product.size && Array.isArray(product.size) ? (
product.color.map((item, i) => (
<option key={i} value={i}>
{item}
</option>
))
) : (
<option value="">No sizes available</option>
)
}
</select>
{/* <p>
<strong>Current value:</strong>
{color}
</p>*/}
</div>
</div>
</div>
<div className="cart-box">
<h1 className="price-cart-box">{"$"+(product.price+priceInFunctionOfColorAndSize)*varyOfQuantity}</h1>
<h1 className="stock-cart-box">In Stock</h1>
<div className="cart-box-buttons">
<select className="quantity-select-button" value={quantity} onChange={(event) => {setQuantity(event.target.value);}}>
{
product.quantity ? (
[...Array(product.stock).keys()].map((x) => (
<option key={x+1} value={x+1}>
{x+1}
</option>
))
) : (
<option value="">No sizes available</option>
)
}
</select>
{/* <button className="cart-button" onClick={addToCartHandler}>Add to cart</button>*/}
<button className="cart-button" onClick={handleAddToCart}>Add to cart</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default ProductScreen;
App.Js
import React from 'react';
import {BrowserRouter,Route, Routes,Link} from 'react-router-dom'
import HomeScreen from './screens/HomeScreen';
import ProductScreen from './screens/ProductScreen';
import CartScreen from './screens/CartScreen';
{/* import {StoreProvider} from './Store';
import Badge from 'react-bootstrap/Badge';
import {LinkContainer} from 'react-router-bootstrap';
import {useContext} from 'react';
import {Store} from './Store';*/}
function App() {
{/* const {state, dispatch: ctxDispatch} = useContext();
const {cart} = state;*/}
return (
<BrowserRouter>
<div>
<nav>
<nav>
{/* <StoreProvider>*/}
<div className="menu-background">
{/*<p className="menu" >Amazonas</p>*/}
<Link to="/" className="menu" >amazonas</Link>
</div>
{/* </StoreProvider>*/}
<div className="logo-background">
<p className="logo">Menu</p>
</div>
</nav>
</nav>
</div>
<Routes>
<Route path="/product/:_id" element={<ProductScreen />}></Route>
<Route path="/cart/:id?" element={<CartScreen />}></Route>
<Route path="/" element={<HomeScreen />}></Route>
</Routes>
</BrowserRouter>
)
}
export default App;
HomeScreen
import React,{useState,useReducer,useEffect} from 'react';
import {Link } from 'react-router-dom';
import axios from 'axios';
import logger from 'use-reducer-logger';
const reducer = (state,action) => {
switch(action.type){
case 'FETCH_REQUEST':
return {...state,loading: true};
case 'FETCH_SUCCESS':
return {...state,products: action.payload,loading:false};
case 'FETCH_FAIL':
return {...state,loading:false,error: action.payload};
default:
return state;
}
};
function HomeScreen(){
const [{loading, error, products},dispatch] = useReducer(logger(reducer),{
products: [],
loading: true,
error: '',
});
useEffect(()=>{
const fetchData = async()=>{
dispatch({type: 'FETCH_REQUEST'});
try{
const result = await axios.get('/api/products');
dispatch({type: 'FETCH_SUCCESS',payload:result.data})
}catch(err){
dispatch({type: 'FETCH_FAIL', payload: err.message});
}
const result = await axios.get('/api/products');
};
fetchData();
},[]);
return (
loading?<div>Loading...</div>
:error? <div>{error}</div>
:
<div>
<body>
<nav>
<div className="menu-background">
{/*<p className="menu" >Amazonas</p>*/}
<Link to="/" className="menu" >amazonas</Link>
</div>
<div className="logo-background">
<p className="logo">Menu</p>
</div>
</nav>
<ul className="products">
{
products.map(product=>
<li>
<div className="product">
<Link to={`/product/${product.name}`}>
<img className="image" src={product.image} alt={product.name} ></img>
</Link>
<Link to={`/product/${product.name}`}>{product.name}</Link>
<div className="rating">{product.rating}</div>
<div className="price">{"$"+product.price}</div>
</div>
</li>
)
}
</ul>
</body>
</div>
)
}
export default HomeScreen;