I have this program where Product.js just showing a list of items with an addToCart button. In the Cart.js, I am trying to show just the items I selected. Following are the files:
App.js
import './App.css';
import React,{useState} from 'react';
import {
Route,
BrowserRouter as Router,
Switch,
} from 'react-router-dom';
import Cart from './components/Cart';
import Product from './components/Product';
import {ProductProvider} from './ItemListContext';
function App() {
const [cart, setCart]= useState([]);
const addToCart=(product)=>{
setCart([...cart, {...product}])
}
console.log(cart)
return (
<div className="App">
<ProductProvider>
<Router>
<Switch>
<Route path="/" exact
render ={()=> < Product addToCart={addToCart}/>}
/>
<Route path="/cart/" exact
render ={()=> < Cart cart = {cart} />}
/>
</Switch>
</Router>
</ProductProvider>
</div>
);
}
export default App;
Product.js
import React,{useContext, useState} from 'react';
import {ProductContext} from '../ItemListContext';
export default function Product({addToCart}) {
const [products, setProducts] = useContext(ProductContext)
return(
<div className="main-page">
products
<h1>Product Page </h1>
<div className="products" >
{products.map((product, idx)=>(
<div key={idx}>
<h3>{product.name} </h3>
<img src= {product.image} /> cost = {product.cost}
<button onClick={()=>addToCart(product)}
>Add to Cart</button>
</div>
))}
</div>
<div>
</div>
</div>
)
}
ItemListContext.js
import React,{createContext, useState} from 'react';
export const ProductContext = createContext();
export function ProductProvider(props) {
const [products, setProducts]=useState([
{
name: 'iPhone',
cost : '$899.99',
image: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQB6BMWrPXA9KyTtxa6o600mjeUNJ7zSXgaNt--FDCR6YjQ4XWS5G1J3dSF5ChurfQEGxorkxYs&usqp=CAc',
},
{
name: 'Samsung',
cost : '$599.99',
image: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUGMCcF3_XBIKH5Dja-9iCkRP4CSA-CYaylQ&usqp=CAU'
}
])
return (
<div>
<ProductContext.Provider value={[products, setProducts]} >
{props.children}
</ProductContext.Provider>
</div>
)
}
Cart.jsx
import React from 'react';
export default function Cart({cart}) {
console.log()
return (
<div className="cart">
<h1>cart {cart.length}</h1>
<div className="products" >
{cart.map((product, idx)=>(
<div key={idx}>
<h3>{product.name}</h3>
<h4>{product.cost}</h4>
<img src={product.image} alt = {product.name} />
</div>
))}
</div>
<div>
</div>
</div>
)
}
I am trying to create the router link, localhost:3000/ is showing the product list, but localhost:3000/cart/ doesn't show the cart items.
However, if I remove the Routers and run the program like this:
App.js
import './App.css';
import React,{useState} from 'react';
import {
Route,
BrowserRouter as Router,
Switch,
} from 'react-router-dom';
import Cart from './components/Cart';
import Product from './components/Product';
import {ProductProvider} from './ItemListContext';
function App() {
const [cart, setCart]= useState([]);
const addToCart=(product)=>{
setCart([...cart, {...product}])
}
console.log(cart)
return (
<div className="App">
<ProductProvider>
< Product addToCart={addToCart}/>
<Cart cart={cart} />
</ProductProvider>
</div>
);
}
export default App;
the program works just fine.
So my question is, am I doing my Routing the right way? Is this the right way to pass the cart prop?
There are no problem with Routing, you can add the Link above that and it works as expected https://codesandbox.io/s/solitary-river-hvv2q
...
<ProductProvider>
<Router>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/cart">Cart</Link>
</li>
</ul>
<Switch>
<Route path="/" exact>
<Product addToCart={addToCart} />
</Route>
<Route path="/cart/" exact>
<Cart cart={cart} />
</Route>
</Switch>
</Router>
</ProductProvider>
...
When you directly navigate to /cart by typing that link on browser, your App is re-render then cart is set to empty array, you should store it in storage to prevent that issue.
Related
import React, { useEffect, useState } from 'react'
import { Link } from 'react-router-dom';
import './Allproducts.css'
import Categories from './categories.json'
import ForYouItem from './ForYouItem'
export default function Allproducts(props) {
const [products, setProducts] = useState([]);
useEffect(() => {
fetch(`https://fakestoreapi.com/products/category/${props.category}`)
.then((res) => res.json())
.then((data) => setProducts(data))
}, [])
return (
<>
<div className="banner">
<h1>All Products</h1>
<h4>Get best items in budget</h4>
</div>
<div className="main-grid">
<div className="left-grid">
<div className="left-categories">
<h1>Collections</h1>
{Categories.map((category) => {
let Afeef = `/${props.category}`
return (
<Link to= {Afeef} className='products-categories'> <h4>{category.title}</h4></Link>
)
}
)}
</div>
</div>
<div className="right-grid">
<div className="row ">
{products.map((product) => {
return (
<div className="col-md-4 my-2 Products-1">
<ForYouItem Title={product.title.slice(0, 50)} Price={product.price} Imageurl={product.image} rate={product.rating.rate} count={product.rating.count} />
</div>
)
}
)}
</div>
</div>
</div>
</>
)
}
So in this code I am calling same prop two times, first in this line;
fetch(https://fakestoreapi.com/products/category/${props.category})
Secondly here;
let Afeef = /${props.category}
The prop is working in the First line but on the second line it gives no result. The link isn't changed.
What I want is when I click on second Link I get redirected "/${props.category}" but the URL is not changing
Code for App.js:
import React, { Component } from 'react'
import './App.css';
import NavBar from './components/NavBar';
import TopBar from './components/TopBar'
import {
HashRouter,
Routes,
Route,
} from "react-router-dom";
import Mainpage from './Mainpage';
import Login from './components/Login';
import Signup from './components/Signup';
import Allproducts from './components/Allproducts';
function App() {
return (
<div>
<HashRouter>
<TopBar/>
<NavBar/>
<Routes>
<Route path="/" element={<Mainpage/>}></Route>
<Route path="/Login" element={<Login/>}></Route>
<Route path="/Signup" element={<Signup/>}></Route>
<Route path="/jewelery" element={<Allproducts category="jewelery"/>}></Route>
<Route path="/electronics" element={<Allproducts category="electronics"/>}></Route>
<Route path="/men's clothing" element={<Allproducts category="men's clothing"/>}></Route>
<Route path="/women's clothing" element={<Allproducts category="women's clothing"/>}></Route>
</Routes>
</HashRouter>
</div>
);
}
export default App;
I'm new to react and I'm trying to build application to make reservation for fishing charters for a school project I'm working on. I'm using react-router-dom which works for the most part, but when I try and use a button to navigate to page it does not render components on 2 of the pages. The page will refresh but it does not render the components "CharterDetails" or "BookCharter".
I get no errors but I do get a warning that says:
No routes matched location "/charterdetails/62fb097cb985e11cb3884f6e"
It does not seem to matter if I use the button handler or just a link both options give the same result for both CharterDetails and BookCharter, navigation for other pages render as expected.
Click here for my GitHub repository
select the work-in-progress branch
hope I’m explaining clear enough. Thank for your time
App.js:
import React, { useState, useEffect } from "react";
import Nav from "./Components/Nav";
import {
BrowserRouter as Router,
Route,
Routes,
useParams,
} from "react-router-dom";
import Login from "./Components/Users/LoginForm";
import "./App.css";
import Landings from "./Pages/Landings.js";
import Boats from "./Pages/Boats";
import Charters from "./Pages/Charters";
import CharterDetails from "./Pages/CharterDetails";
import BookCharter from "./Pages/BookCharter";
import PageNotFound from "./Pages/404";
import Home from "./Pages/Home";
function App() {
const { id } = useParams();
console.log("useParams", id);
return (
<>
<header>
<img
src="../assets/Images/scsfcBadge.png"
alt="SoCal Sportfishing Club"
/>
SoCal Sportfishing Club
</header>
<div className="main">
<Router>
<aside className="left">
<Nav />
</aside>
<main>
<Routes>
<Route index element={<Home />} />
<Route path="/charters" element={<Charters />} />
<Route path="/landings" element={<Landings />} />
<Route path="/boats" element={<Boats />} />
{/* need to add parameter :id to link */}
<Route page="/bookcharter/" element={<BookCharter />} />
{/* need to add parameter :id to link */}
<Route page="/charterdetails/:id" element={<CharterDetails />} />
<Route page="*" element={<PageNotFound />} />
</Routes>
</main>
<aside className="right">
<Login />
</aside>
</Router>
</div>
<footer>Copyright © 2022 SoCal SportFishing Club </footer>
</>
);
}
export default App;
Home.js:
import React,{useState , useEffect} from 'react';
import { Link, useNavigate } from "react-router-dom";
import { BrowserRouter as Router, Route, Routes, useParams } from "react-router-dom";
function Home(){
const navigate = useNavigate();
const [charterData, setCharterData] = useState([]);
const [charterid, setCharterid] = useState('');
useEffect(() => {
// declare the async data fetching function
const fetchData = async () => {
fetch('http://localhost:5000/charter/featured/')
.then((response) => response.json())
.then((data) => setCharterData(data));
console.log('Charter ', charterData)
}
// call the function
fetchData()
// make sure to catch any error
.catch(console.error);
}, [])
function handleClick(charter) {
let id = charter.id;
let path = `/charterdetails//${id}`
navigate(path);
}
function BookClick(e) {
// e.preventDefault();
let path = `/bookcharter/${e.target.id}`
navigate(path);
}
return(
<div className="container">
{
charterData.map((charter, index) => {
return(<div key={index} className="card">
<div className="card-header">
</div>
<img src={'../assets/Images/charters/' + charter.Img} alt={charter.CharterName} />
<div className="tag tag-teal">{charter.BoatName} - {charter.Duration}</div>
<div className="card-body">
<div style={{fontSize:'28px', fontWeight: 'Bold'}}>
{charter.CharterName}
</div>
<p style={{fontSize:'16px'}}>Departure date: {new Date(charter.Departure).toDateString()}<br />
Return date: {new Date(charter.Return).toDateString()}<br />
Trip Duration: {charter.Duration}<br />
Price: ${charter.Cost}<br />
Max Load:{charter.MaxLoad}<br />
Target: {charter.Target}<br /></p>
<div style={{textAlign:'center', width: '100%'}}>
<Link
to= {{
pathname:`/charterdetails/${charter.id}`
}}
>
<button>Details</button>
</Link>
<button onClick={BookClick}>Book</button>
</div>
</div>
</div>)
})
}
</div>
)
}
export default Home;
Nav.js:
import React from 'react';
import { Link } from "react-router-dom";
export default function Nav() {
return (
<>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/landings">Landings</Link>
</li>
<li>
<Link to="/boats">Boats</Link>
</li>
<li>
<Link to="/charters">Club Charters</Link>
</li>
<li>
<Link to="/charterdetails">Charter Details</Link>
</li>
<li>
<Link to="/bookcharter">Book Charter</Link>
</li>
</ul>
</>
);
}
CharterDetails.js:
import React from 'react';
function CharterDetails(){
return(
<div>
Charter Details
</div>
)
}
export default CharterDetails;
BookCharter.js:
import React from "react";
function BookCharter(){
return(
<>
Book Charter
</>
)
}
export default BookCharter;
In the app.js I had page instead of path on the route.
Changed from
<Route page="/bookcharter" element={<BookCharter />} />
<Route page="/charterdetails/:id" element={<CharterDetails />} />
to
<Route exact path="/bookcharter" element={<BookCharter />} />
<Route exact path="/charterdetails/:id" element={<CharterDetails />} />
I know this should be very simple. Yet, again useParamas() is returning undefined. My code is as per below:
App.js:
import "./App.css";
import Layout from "./UI/Layout";
import { Route, Routes } from "react-router-dom";
import Home from "./components/Pages/Home";
import { Suspense } from "react";
import Patients from "./components/Pages/Patients";
import Patient from "./components/Pages/Patient";
function App() {
return (
<Layout>
<Suspense>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/patients" element={<Patients />} />
<Route path="/patients/:id" element={<Patient />} />
</Routes>
</Suspense>
</Layout>
);
}
Patient.js
import { useParams } from "react-router-dom";
import Card from "../../UI/Card";
import loading from "../../UI/loading.svg";
function Patient() {
const { id } = useParams;
console.log(id);
return (
<div className="App">
<header className="header">
<p>This is the page for patient with id: {id}!</p>
</header>
<div className="container">
<Card>
<div>
<img src={loading} className="loading" alt="logo" />
</div>
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</Card>
</div>
</div>
);
}
export default Patient;
Patients.js
import Card from "../../UI/Card";
import loading from "../../UI/loading.svg";
import { Link } from "react-router-dom";
function Patients() {
return (
<div className="App">
<header className="header">
<p>This is the patients' page!</p>
</header>
<div className="container">
<Card>
<div>
<img src={loading} className="loading" alt="logo" />
</div>
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<Link to="/patients/12">Go to patient with id 12</Link>
</Card>
</div>
</div>
);
}
export default Patients;
and index.js
import React from "react";
import ReactDOM from "react-dom/client";
import { HashRouter } from "react-router-dom";
import "./index.css";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<HashRouter>
<App />
</HashRouter>
);
Please someone let me know what is missing that id is returning undefined?
Note: I followed also from the link Using the useParams hook in react and https://www.youtube.com/watch?v=UjHT_NKR_gU&t=1098s.
Your useParams is imported and used ok, except your forgot paranthesis after useParams in Parient component:
function Patient() {
const { id } = useParams() <== here
Good morning community StackOverflow.I had to use the route to access some component inside the application but that's not work for me despite I had installed the "npm install react-router-dom" the browser render me a blank file,so this is all my file :
app.js file :
import React from 'react';
import HomeScreen from './screens/HomeScreen';
import ProductScreen from './screens/ProductScreen';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div className="grid-container" >
<header className="row" >
<div>
<a className="brand" href="/">My Shop</a>
</div>
<div>
Cart
Sign In
</div>
</header >
<main>
<Route path="/" component={HomeScreen} ></Route>
<Route path="/product/:id" component={ProductScreen} ></Route>
</main>
<footer classNameName="row center" >All right reserved</footer>
</div>
</BrowserRouter>
);
}
export default App;
this is the HomeScreen file :
import React from "react";
import {data} from '../data';
import Product from '../components/Product';
function HomeScreen () {
return (
<div>
<div className="row center">
{data.products.map((product) => (
<Product key={product._id} product={product} ></Product>
))}
</div>
</div>
)
};
export default HomeScreen;
this is the ProductScreen file :
import React from "react";
function ProductScreen () {
return (
<div>Product Screen</div>
)
};
export default ProductScreen;
this is the Product file code:
import React from 'react';
import Rating from './Rating';
function Product (props) {
const {product} = props;
return (
<div className="card">
<a href="product.html">
<img className="medium" src={product.image} alt={product.name} />
</a>
<div className="card-body">
<a href="product.html">
<h2>{product.name}</h2>
</a>
<Rating rating={product.rating} numReviews={product.numReviews} ></Rating>
<div className="price" >${product.price}</div>
</div>
</div>
)
}
export default Product;
In react router v6, lots of keywords have changed. In addition, various functions like useHistory have also been changed. Check the package version in package.json file. You can also check your browser console for errors.
In case you have v6 or above, change your app.js as below, to make it work. I have changed the react router keywords, indented code and made Route tag as self closing.
import React from 'react';
import HomeScreen from './screens/HomeScreen';
import ProductScreen from './screens/ProductScreen';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
function App() {
return (
<Router>
<div className="grid-container" >
<header className="row" >
<div>
<a className="brand" href="/">My Shop</a>
</div>
<div>
Cart
Sign In
</div>
</header>
<main>
<Routes>
<Route path="/" element={<HomeScreen />} />
<Route path="/product/:id" element={<ProductScreen />} />
</Routes>
</main>
<footer classNameName="row center" >All right reserved</footer>
</div>
</Router>
);
}
export default App;
If you're using version 6, you have to wrap <Route> components with <Routes> (you should import the component first), otherwise, wrap them with <Switch> component
I want my find function to match the id of data.js with id of the product that user clicked so that i can go to the specific details of product user clicked. But when i add the .find function it says error with cannot read property image of undefined.
import React, { useState } from 'react';
import Navbar from './components/Navbar';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
import ProductScreen from './screens/ProductScreen';
import HomeScreen from './screens/HomeScreen';
import AppFront from './appfront/AppFront';
function App(){
return (
<Router>
<Navbar />
<main>
<Route path='/' component={AppFront} exact />
<Route path='/' component={HomeScreen} exact />
<Route path="/product/:id" component={ProductScreen} />
</main>
</Router>
)
}
export default App
And my ProductScreen code
import React from 'react'
import Rating from '../components/Rating';
import data from '../data'
function ProductScreen(props) {
const product = data.products.find(x => x._id === props.match.params.id)
// if(!product){
// return <div>Product not available</div>
// }
return (
<div className='product-container'>
<div className='product-img'>
<img src={product.image} alt={product.title} />
</div>
<div className='product-details'>
<h3>{product.title}</h3>
<Rating rating={product.rating} numReviews={product.numReviews}/>
<p>{product.numReviews}</p>
<h2>Rs. {product.price}</h2>
<div className='btn-product-container'>
<button className='btn'>Buy Now</button>
<button className='btn'>Add to Cart</button>
</div>
</div>
</div>
)
}
export default ProductScreen