I've finished this project, it's just that whenever React routes, my home snapshot switch case re-renders a second time.
Here is the code for Home page
const Home = (props) => {
const dispatch = useDispatch();
const userName = useSelector(selectUserName);
let recommends = [];
let newDisneys = [];
let originals = [];
let trending = [];
useEffect(() => {
db.collection("movies").onSnapshot((snapshot) => {
snapshot.docs.map((doc) => {
switch (doc.data().type) {
case "recommend":
recommends = [...recommends, { id: doc.id, ...doc.data() }];
break;
case "new":
newDisneys = [...newDisneys, { id: doc.id, ...doc.data() }];
break;
case "original":
originals = [...originals, { id: doc.id, ...doc.data() }];
break;
case "trending":
trending = [...trending, { id: doc.id, ...doc.data() }];
break;
}
});
dispatch(
setMovies({
recommend: recommends,
newDisney: newDisneys,
original: originals,
trending: trending,
})
);
});
}, [userName]);
return (
<Container>
<ImgSlider />
<Viewers />
<Recommends />
<NewDisney />
<Originals />
<Trending />
</Container>
);
}
export default Home;
And here is the code for the App.js :
import React from 'react';
import './App.css';
import Nav from './components/Nav.jsx'
import Home from './components/Home.jsx';
import {
BrowserRouter as Router,
Routes,
Route,
} from "react-router-dom";
import Detail from './components/Detail';
import Login from './components/Login';
function App() {
return (
<div className="App">
<Router>
<Nav />
<Routes>
<Route exact path="/" element={<Login />} />
<Route path="/detail/:id" element={<Detail />} />
<Route path="/home" element={<Home />} />
</Routes>
</Router>
</div>
);
}
export default App;
My Navigation page:
const Nav = (props) => {
const dispatch = useDispatch()
const navigate = useNavigate()
const userName = useSelector(selectUserName)
const userPhoto = useSelector(selectUserPhoto)
useEffect(() => {
auth.onAuthStateChanged(async (user) => {
if (user) {
setUser(user)
navigate("/home")
}
});
}, [userName])
const handleAuth = () => {
if (!userName) {
auth
.signInWithPopup(provider)
.then((result) => {
setUser(result.user)
})
.catch((error) => {
alert(error.message)
});
}
else if (userName) {
auth
.signOut()
.then(() => {
dispatch(setSignOutState())
navigate("/")
})
.catch((err) => alert(err.message))
}
}
const setUser = (user) => {
dispatch(
setUserLoginDetails({
name: user.displayName,
email: user.email,
photo: user.photoURL,
})
);
};
return (
<Header>
<Logo src="/images/logo.svg" alt="Disney+" />
{ !userName ? (<Login onClick={handleAuth}>Login</Login>) : (
<>
<NavMenu>
<Link to="/home">
<img src="/images/home-icon.svg" alt="Home" />
<span>HOME</span>
</Link>
<Link to="/home">
<img src="/images/search-icon.svg" alt="Search" />
<span>SEARCH</span>
</Link>
<Link to="/home" href="Watchlist">
<img src="/images/watchlist-icon.svg" alt="Watchlist" />
<span>WATCHLIST</span>
</Link>
<Link to="/home">
<img src="/images/original-icon.svg" alt="Originals" />
<span>ORIGINALS</span>
</Link>
<Link to="/home">
<img src="/images/movie-icon.svg" alt="Movies" />
<span>MOVIES</span>
</Link>
<Link to="/home">
<img src="/images/series-icon.svg" alt="Series" />
<span>SERIES</span>
</Link>
</NavMenu>
<SignOut>
<UserImg src={userPhoto} alt={userName}/>
<DropDown>
<span onClick={handleAuth}>Sign Out</span>
</DropDown>
</SignOut>
</>
)}
</Header>
);
}
I'm completely lost as to why it renders my , , and a second time. If I refresh the page, the second render disappears, but once I try to click on a link and use my Nav to route back to the home page, it appears again.
Related
As you can see the photo:
When I input the http:localhost:3000/ or some else url.
It all be redirected the wrong web:http:localhost:3000/product/productID
here are the relative codes:
App.jsx.
This one is setting path for the route.
import React from 'react'
import Cart from './pages/Cart'
import Home from './pages/Home'
import Login from './pages/Login'
import Product from './pages/Product'
import ProductList from './pages/ProductList'
import Register from './pages/Register'
import { BrowserRouter as Router, Navigate, Route, Routes } from "react-router-dom";
const App = () => {
const user = true;
return (
<Router>
<Routes>
<Route exact path="/" element={<Home />} />
<Route exact path="/products/:category" element={<ProductList />} />
<Route exact path="/product/:id" element={<Product />} />
<Route exact path="/cart" element={<Cart />} />
<Route exact path="/register" element={user ? <Navigate to="/" /> : <Register />} />
<Route exact path="/login" element={user ? <Navigate to="/" /> : <Login />} />
</Routes>
</Router>
)
}
export default App
Product.jsx This one is running product information,it's also a component.
When I run the url:http:localhost:3000/products/women,it should be show the products belongs to the category:women.
But it runs http:localhost:3000/products/productId,it's wrong.
import React from 'react'
import { useEffect, useState } from 'react';
import Product from './Product';
import axios from "axios"
const Products = ({ cate, filters, sort }) => {
//const Products = () => {
console.log(cate, filters, sort)
const [products, setProducts] = useState([]);
const [filteredProducts, setFilteredProducts] = useState([]);
useEffect(() => {
const getProducts = () => {
const res = axios.get(
cate ? `http://localhost:8000/api/products?category=${cate}`
: "http://localhost:8000/api/products")
.then(
function (res) {
setProducts(res.data);
console.log(res)
}
).catch(
function (err) {
console.log(err)
});
}
getProducts();
}, [cate]);
useEffect(() => {
cate && setFilteredProducts(
products.filter((item) => (
Object.entries(filters).every(([key, value]) => {
return item[key].includes(value);
}
)
))
)
}, [products, cate, filters])
useEffect(() => {
if ((sort === "newest")) {
setFilteredProducts((prev) =>
[...prev].sort((a, b) => a.createdAt.localeCompare(b.createdAt))
)
} else if (sort === "asc") {
setFilteredProducts((prev) =>
[...prev].sort((a, b) => a.price - b.price)
)
} else {
setFilteredProducts((prev) =>
[...prev].sort((a, b) => b.price - a.price)
)
}
},[sort])
return (
<Container >
{cate
? filteredProducts.map((item) => (
<Product item={item} key={item._id} />))
: products.slice(0, 8).map((item) => <Product item={item} key={item._id} />)}
</Container>
);
};
pages/Product.jsx.
This one is running display part.
http:localhost:3000/product/productID**
import { useLocation } from 'react-router-dom'
import { useState, useEffect } from 'react';
import { publicRequest } from './requestMethods';
const Product = () => {
// 回傳路徑
const location = useLocation();
const id = location.pathname.split("/")[2];
const [product, setProduct] = useState({});
useEffect(() => {
const getProduct = async () => {
try {
const res = await publicRequest.get("/product/find/" + id);
setProduct(res.data);
}
catch { }
}
getProduct();
}, [id])
ProuctList.jsx
import React from 'react'
import { mobile } from './../responsive'
import { useLocation } from 'react-router-dom';
import { useState } from 'react';
const ProductList = () => {
//回傳路徑
const location = useLocation();
const cate = location.pathname.split("/")[2];
console.log(location);
//設定selector的值,並且回傳
const [filters, setFilters] = useState({});
const [sort, setSort] = useState("newest");
const handleFilters = (e) => {
const value = e.target.value;
setFilters({
...filters,
[e.target.name]: value,
});
};
console.log(filters)
return (
<Container>
<Navbar />
<Announcement />
<Title>Dresses</Title>
<FilterContainer>
<Filter><FilterText>Filter Products:</FilterText>
<Select name="color" onChange={handleFilters}>
<Option disabled>Color</Option>
<Option>black</Option>
<Option>white</Option>
<Option>green</Option>
<Option>wheat</Option>
<Option>black</Option>
<Option>red</Option>
<Option>blue</Option>
</Select>
<Select name="size" onChange={handleFilters}>
<Option disabled>Size</Option>
<Option>XS</Option>
<Option>S</Option>
<Option>M</Option>
<Option>L</Option>
<Option>XL</Option>
</Select></Filter>
<Filter><FilterText>Sort Products:
<Select onChange={(e) => setSort(e.target.value)}>
<Option value="newest">Newest</Option>
<Option value="asc">Price(asc)</Option>
<Option value="desc">Price(desc)</Option>
</Select></FilterText></Filter>
</FilterContainer>
<Products cate={cate} filters={filters} sort={sort} />
<NewsLetter />
<Footer />
</Container>
)
}
I found that the bottom code will make the all pages redirect to the http:localhost:3000/product/productID
components/Product.jsx
const Product = ({ item }) => {
return (
<Container className='container product'>
<Circle />
<Img src={item.img} />
<Info >
<Icon >
<ShoppingCartOutlinedIcon />
</Icon>
<Icon>
<Navigate to={`/product/${item._id}`}>
<SearchOutlinedIcon />
</Navigate>
</Icon>
<Icon>
<FavoriteBorderOutlinedIcon />
</Icon>
</Info>
</Container>
)
}
The Product component is rendering a Navigate component to "/product/XXX" when it is rendered. Rendering <Navigate /> will immediately effect a navigation action. It seems this Product component is rendered as part of a list when rendering all the products. It's likely you meant to render a Link component instead so the navigation isn't effected until the search icon is clicked.
const Product = ({ item }) => {
return (
<Container className='container product'>
<Circle />
<Img src={item.img} />
<Info >
<Icon >
<ShoppingCartOutlinedIcon />
</Icon>
<Icon>
<Link to={`/product/${item._id}`}> // <-- use Link component
<SearchOutlinedIcon />
</Link>
</Icon>
<Icon>
<FavoriteBorderOutlinedIcon />
</Icon>
</Info>
</Container>
);
};
Pagination is not working in React Frontend. I am creating an Ecommerce Application and want to Paginate my products on my website. Here is the Code for Getting Product with Pagination.
const getProducts = asyncHandler(async (req, res, next) => {
const pageSize = 3;
const page = Number(req.query.pageNumber) || 1;
const keyword = req.query.keyword
? {
name: {
$regex: req.query.keyword,
$options: 'i',
},
}
: {};
const count = await Product.countDocuments({ ...keyword });
const products = await Product.find({ ...keyword })
.limit(pageSize)
.skip(pageSize * (page - 1))
.sort({ _id: -1 });
res.json({ products, page, pages: Math.ceil(count / pageSize) });
});
I am using Redux for state Management. Here is the code for the Reducer
// PRODUCT LIST
export const productListReducer = (state = { products: [] }, action) => {
switch (action.type) {
case PRODUCT_LIST_REQUEST:
return { loading: true, products: [] };
case PRODUCT_LIST_SUCCESS:
return {
loading: false,
pages: action.payload.pages,
page: action.payload.page,
products: action.payload.products,
};
case PRODUCT_LIST_FAIL:
return { loading: false, error: action.payload };
default:
return state;
}
};
And here is the Action code
// PRODUCT LIST
export const listProduct =
(keyword = ' ', pageNumber = ' ') =>
async (dispatch) => {
try {
dispatch({ type: PRODUCT_LIST_REQUEST });
const { data } = await axios.get(
`/api/products?keyword=${keyword}&pageNumber=${pageNumber}`
);
dispatch({ type: PRODUCT_LIST_SUCCESS, payload: data });
} catch (error) {
dispatch({
type: PRODUCT_LIST_FAIL,
payload:
error.response && error.response.data.error
? error.response.data.error
: error.message,
});
}
};
And this is the Component for pagination and few others
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import Rating from './Rating';
import Pagination from './pagination';
import { useDispatch, useSelector } from 'react-redux';
import { listProduct } from '../../Redux/Actions/ProductActions';
import Loading from '../LoadingError/Loading';
import Message from '../LoadingError/Error';
const ShopSection = (props) => {
const { keyword, pagenumber } = props;
const dispatch = useDispatch();
const productList = useSelector((state) => state.productList);
const { loading, error, products, page, pages } = productList;
useEffect(() => {
dispatch(listProduct(keyword, pagenumber));
}, [dispatch, keyword, pagenumber]);
return (
<>
<div className='container'>
<div className='section'>
<div className='row'>
<div className='col-lg-12 col-md-12 article'>
<div className='shopcontainer row'>
{loading ? (
<div className='mb-5'>
<Loading />
</div>
) : error ? (
<Message variant='alert-danger'>{error}</Message>
) : (
<>
{products.map((product) => (
<div
className='shop col-lg-4 col-md-6 col-sm-6'
key={product._id}
>
<div className='border-product'>
<Link to={`/products/${product._id}`}>
<div className='shopBack'>
<img src={product.image} alt={product.name} />
</div>
</Link>
<div className='shoptext'>
<p>
<Link to={`/products/${product._id}`}>
{product.name}
</Link>
</p>
<Rating
value={product.rating}
text={`${product.numReviews} reviews`}
/>
<h3>${product.price}</h3>
</div>
</div>
</div>
))}
</>
)}
{/* Pagination */}
<Pagination
pages={pages}
page={page}
keyword={keyword ? keyword : ''}
/>
</div>
</div>
</div>
</div>
</div>
</>
);
};
export default ShopSection;
And Pagination Component is here
import React from 'react';
import { Link } from 'react-router-dom';
const Pagination = (props) => {
const { page, pages, keyword = '' } = props;
return (
pages > 1 && (
<nav>
<ul className='pagination justify-content-center'>
{[...Array(pages).keys()].map((x) => (
<li
className={`page-item ${x + 1 === page ? 'active' : ''}`}
key={x + 1}
>
<Link
className='page-link'
to={
keyword
? `/search/${keyword}/page/${x + 1}`
: `/page/${x + 1}`
}
>
{x + 1}
</Link>
</li>
))}
</ul>
</nav>
)
);
};
export default Pagination;
And here is my App.js component
import React from 'react';
import './App.css';
import './responsive.css';
import 'react-toastify/dist/ReactToastify.css';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import HomeScreen from './screens/HomeScreen';
import SingleProduct from './screens/SingleProduct';
import Login from './screens/Login';
import Register from './screens/Register';
import CartScreen from './screens/CartScreen';
import ShippingScreen from './screens/ShippingScreen';
import ProfileScreen from './screens/ProfileScreen';
import PaymentScreen from './screens/PaymentScreen';
import PlaceOrderScreen from './screens/PlaceOrderScreen';
import OrderScreen from './screens/OrderScreen';
import NotFound from './screens/NotFound';
import PrivateRouter from './PrivateRoute';
const App = () => {
return (
<Router>
<Switch>
<Route path='/' component={HomeScreen} exact />
<Route path='/search/:keyword' component={HomeScreen} exact />
<Route path='/page/:pagenumber' component={HomeScreen} exact />
<Route
path='/search/:keyword/page/:pageNumber'
component={HomeScreen}
exact
/>
<Route path='/products/:id' component={SingleProduct} />
<Route path='/login' component={Login} />
<Route path='/register' component={Register} />
<PrivateRouter path='/profile' component={ProfileScreen} />
<Route path='/cart/:id?' component={CartScreen} />
<PrivateRouter path='/shipping' component={ShippingScreen} />
<PrivateRouter path='/payment' component={PaymentScreen} />
<PrivateRouter path='/placeorder' component={PlaceOrderScreen} />
<PrivateRouter path='/order/:id' component={OrderScreen} />
<Route path='*' component={NotFound} />
</Switch>
</Router>
);
};
export default App;
When i try to send request from postman the data is returning fine. I have already debug alot and couldn't able to resolve this bug. Help me to resolve this i will be grateful to you
You have to define pagenumber, because it is not defined.
const pagenumber = match.params.pagenumber;
Define it like this.
I hope it will work.
I have this serch.js file. When I search and click on the li in the search result, I want to get redirected to <InnerDetail /> but the URL doesn't change or I don't get redirected to this page
but manualy if I type in the URL localhost/detiled/8 I am redirected to to <InnerDetail /> with id as 8
import React from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faSearch } from "#fortawesome/free-solid-svg-icons";
import { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { useHistory } from "react-router-dom";
const initialState = {
idaddProducts: "",
};
const Searchclients = () => {
const history = useHistory();
const [showResults, setShowResults] = React.useState(true);
const [poName, pnName] = React.useState(initialState);
const [showSerch, setShowSerch] = React.useState([]);
const [detail, setDetail] = useState(false);
const [inputValue, setInputValue] = React.useState("");
const [filteredSuggestions, setFilteredSuggestions] = React.useState([]);
const [selectedSuggestion, setSelectedSuggestion] = React.useState(0);
const [displaySuggestions, setDisplaySuggestions] = React.useState(false);
const suggestions = [];
showSerch.forEach(function (data) {
suggestions.push(data);
});
const onChange = (event) => {
const value = event.target.value;
setInputValue(value);
setShowResults(false);
const filteredSuggestions = suggestions.filter(
(suggestion) =>
suggestion.firstname
.toString()
.toLowerCase()
.includes(value.toLowerCase()) ||
suggestion.id.toString().toLowerCase().includes(value.toLowerCase())
);
setFilteredSuggestions(filteredSuggestions);
setDisplaySuggestions(true);
};
const onSelectSuggestion = (index) => {
setSelectedSuggestion(index);
setInputValue(filteredSuggestions[index]);
setFilteredSuggestions([]);
setDisplaySuggestions(false);
};
const SuggestionsList = (props) => {
// console.log(props);
const {
suggestions,
inputValue,
onSelectSuggestion,
displaySuggestions,
selectedSuggestion,
} = props;
if (inputValue && displaySuggestions) {
if (suggestions.length > 0) {
return (
<ul className="suggestions-list" style={styles.ulstyle}>
{suggestions.map((suggestion, index) => {
// console.log(suggestions);
const isSelected = selectedSuggestion === index;
const classname = `suggestion ${isSelected ? "selected" : ""}`;
return (
<Link to={`/detiled/${suggestion.id}`}> //this link dont work
<li
style={styles.listyle}
// onMouseOver={{ background: "yellow" }}
key={index}
className={classname}
>
{suggestion.firstname}
</li>
</Link>
);
})}
</ul>
);
} else {
return <div>No suggestions available...</div>;
}
}
return <></>;
};
useEffect(() => {
axios
.get("all-doctors-list/")
.then((res) => {
const data = res.data;
// pnName(data.data);
// var stringdata = data;
setShowSerch(data);
//console.log(stringdata);
});
// setShowSerch(data);
}, []);
return (
<>
<div className="note-container" style={styles.card}>
<div style={styles.inner}>
<p style={{ textAlign: "left" }}>Search Doctors</p>
<form className="search-form" style={{}}>
{showResults ? (
<FontAwesomeIcon
style={{ marginRight: "-23px" }}
icon={faSearch}
/>
) : null}
<input
onChange={onChange}
value={inputValue}
style={styles.input}
type="Search"
/>
<SuggestionsList
inputValue={inputValue}
selectedSuggestion={selectedSuggestion}
onSelectSuggestion={onSelectSuggestion}
displaySuggestions={displaySuggestions}
suggestions={filteredSuggestions}
/>
</form>
</div>
</div>
</>
);
};
export default Searchclients;
Navigator.js
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import InnerDetail from "./client/doctor/components/innerto_detail.js";
class Navigator extends React.Component {
render() {
return (
<Router>
<div>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/detiled/:id">
<InnerDetail />
</Route>
</Switch>
</div>
</Router>
);
}
}
function Home() {
return (
<div style={{ paddingTop: "20%", textAlign: "center" }}>
<h1>Home</h1>
</div>
);
}
export default Navigator;
when i hover on the<li> the bottom of the browser the path is showing currectly
i think the problem is here i tried another links here nothing is working here
<Link to={`/detiled/${suggestion.id}`}> //this link dont work
<li
style={styles.listyle}
// onMouseOver={{ background: "yellow" }}
key={index}
className={classname}
>
{suggestion.firstname}
</li>
</Link>
i tryed another link under the flowing code
a button called hello and that works i think the probelm is with the return
<SuggestionsList
inputValue={inputValue}
selectedSuggestion={selectedSuggestion}
onSelectSuggestion={onSelectSuggestion}
displaySuggestions={displaySuggestions}
suggestions={filteredSuggestions}
/>
<Link
to={{
pathname: `/detiled/5`,
}}
>
<button>hello</button>
</Link>
try using
<Route path="/detiled/:id" component={InnerDetail} />
instead of
<Route path="/detiled/:id">
<InnerDetail />`
in Navigator.js
and
Route exact path="/">
<Home />
did you created any Home component, and not imported that in Navigator.js
<Link to={"/detiled/"+ suggestion.id}><li>...</li></Link>
this worked for me
I am a newbie trying to build a React blog. Routes etc work fine except when a dynamic route comes into question. The Link does not render unless refreshed.
Here is App.js where the Routes are defined
function App() {
const [username, setUsername] = useState('');
const [loggedIn, setLoggedIn] = useState(false);
return (
<>
<Router history={customHistory}>
<div className="App">
<UserContext.Provider value={{ username, setUsername, loggedIn, setLoggedIn }}>
<Navigation />
<Switch>
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route exact path="/blog/:id" component={BlogDetails} />
<Route path="/content" component={Content} />
<Route path="/logout" component={Logout} />
<Route exact path="/" component={Home} />
</Switch>
</UserContext.Provider>
</div>
</Router>
</>
)
}
export default App;
Here is BlogItems.js which calls the :
import { Link } from 'react-router-dom';
function BlogItems() {
const [blogList, setBlogList] = useState([])
useEffect(() => {
Axios.get("http://localhost:3001/api/get"
, { withCredentials: true })
.then((res) => {
setBlogList(res.data);
});
}, []);
return (
<div className="blog-list">
{blogList && blogList.map((blog) => {
return (
<div className="blog-elems" key={blog && blog.id}>
<Link to={`/blog/${blog.id}`}>{blog.title}</Link>
<h6>By <span>Ritu Rawat</span> on {DateFormater(blog.dated)}</h6>
<div className="blog-list-body">{blog && blog.body.slice(0, 200) + '...'}</div>
</div>
);
})}
</div>
) }
export default BlogItems;
and this is the actual BLogDetails Page which needs to be called from the dynamic route:
const BlogDetails = (props) => {
console.log(props);
//const { username } = useContext(UserContext);
const [blog, setBlog] = useState(null);
const { id } = useParams();
useEffect(() => {
console.log("BLOG ARTICLE");
Axios.get(`http://localhost:3001/api/blog/${id}`
, { withCredentials: true })
.then((res) => {
setBlog(res.data[0]);
});
}, [id]);
return (
<>
<div className="blog-background">
<div className="blog-list">
<div className="blog-elems" key={blog && blog.id}>
<h2> {blog && blog.title}</h2>
<h6>By <span>Ritu Rawat</span> on {blog && DateFormater(blog.dated)}</h6>
<div className="blog-list-body">{blog && blog.body}</div>
</div>
<Comments id={id} />
</div>
</div>
</>
)
}
export default BlogDetails;
When I click on the link in the HoverBooks Component to get to a new page where I can render the book location state in Book component, but when I press on it nothing happens. I think the error is in Route:
function App() {
return (
<div className="App">
<Router>
<Switch>
<Route path="/book:/book.Key">
<Book />
</Route>
<Route path="/signin">
<Signin />
</Route>
<Route path="/">
<Header />
<Home />
</Route>
</Switch>
</Router>
</div>
)
}
export default App
import React from 'react'
import { useLocation } from 'react-router-dom'
const Book = () => {
const {
state: { book },
} = useLocation()
console.log({ book })
return (
<div key={book.key}>
<h1>{book.bookName}</h1>
</div>
)
}
export default Book
const HoverBooks = ({ ...book }) => {
const [inHoverBooks, setInHoverBooks] = React.useState(false)
return (
<>
<Link
to={{
pathName: `/book/${book.key}`,
state: {
book,
},
}}
>
<img
onMouseLeave={() => setInHoverBooks(false)}
onMouseEnter={() => setInHoverBooks(true)}
src={book.image}
key={book.key}
/>
</Link>
{inHoverBooks && (
<div className="hover__containter">
<h3>{book.bookName}</h3>
<h2>{book.by}</h2>
<h2>{book.Narreted}</h2>
<h2>{book.length}</h2>
<h2>{book.rating}</h2>
</div>
)}
</>
)
}
export default HoverBooks
Below is the correct form, e.g. /:someName, to define a route with URL params:
<Route path="/book/:bookKey">
<Book />
</Route>
And here is the right syntax to make a Link for the above route:
<Link
to={{
pathname: `/book/SOME_BOOK_KEY`, // replace SOME_BOOK_KEY with some value
state: {
book, // e.g. const book = { key: 'js', bookName: 'Learn JavaScript'}
},
}}
>
<img src="some_src" alt="something" />
</Link>
And you useParams and useLocation react-hooks to access the "URL params" and "location state" in a component:
const Book = () => {
const {
state: { book },
} = useLocation()
const { bookKey } = useParams();
console.log(book, bookKey)
// prints "book" object (from location state) and "bookKey" (from URL params)
return (
<div key={book.key}>
<h1>{book.bookName}</h1>
</div>
)
}
I would suggest you to add typescript to your ReactJS app. It helps you find errors early by doing "static Type-checking".
With react router you need to pass the component you want to render to the Route like this
const ComponentA = (props) => {...}
<Route path="/component-a" component={ComponentA} />
And here is how to link to component a
<Link to="/component-a" >Go to component A</Link>