react link route not redirecting to url - javascript

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

Related

Displaying properties in another page when plus ( + )button is clicked in table

I have created react app. I have directory components with folder pages where I have FindAllMetadata component in which I am making GET request and getting all metadata from API. I am passing loadedMetadata to AllMetadataTable as props. AllMetadataTable component is located in other folder called data. There I am displaying some information about fetched metadata items in table ( Creator, Time Created, Format ) and other fetched properties I am not displaying. In a table aside of the every fetched metadata I have + button which when clicked makes link ( route ) to the new page where I want display all information about fetched metadata, single clicked metadata item. Details component is located in folder pages. I want to display clicked Metadata from AllMetadataTable in Details page or in Metadata component.
Here is my App.js :
import React, { Suspense } from 'react';
import { Switch, Route, BrowserRouter } from 'react-router-dom';
import classes from './App.module.css'
import LoadingSpinner from './components/UI/LoadingSpinner';
import Layout from './components/layout/Layout';
import Footer from './components/layout/Footer';
import RequestMenu from './components/UI/RequestMenu';
// load components only when user gets to them
const Dashboard = React.lazy(() => import('./components/pages/Dashboard'));
const NewData = React.lazy(() => import('./components/pages/NewData'));
const NotFound = React.lazy(() => import('./components/pages/NotFound'));
const FindAllReceivedRequests = React.lazy(() => import('./components/pages/FindAllReceivedRequests'));
const FindAllGivenConsents = React.lazy(() => import('./components/pages/FindAllGivenConsents'));
const ReadConsent = React.lazy(() => import('./components/pages/ReadConsent'));
const FindData = React.lazy(() => import('./components/pages/FindData'));
const FindAllMetadata = React.lazy(() => import ('./components/pages/FindAllMetadata'));
const NewPartnerRequest = React.lazy(() => import('./components/pages/NewPartnerRequest'));
const FindAllGivenRequests = React.lazy(() => import('./components/pages/FindAllGivenRequests'));
const FindAllReceivedConsents = React.lazy(() => import('./components/pages/FindAllReceivedConsents'));
const Metadata = React.lazy(() => import('./components/data/Metadata'));
function App() {
return (
<BrowserRouter>
<Layout>
<Suspense fallback= { <div className = { classes.centered }> <LoadingSpinner /> </div> } >
<Switch>
<Route path ='/' exact>
<Dashboard />
<FindData />
</Route>
<Route path= '/new-data' exact>
<NewData />
</Route>
<Route path= '/metadata' exact>
<FindAllMetadata />
</Route>
<Route path = '/data'>
<Metadata />
</Route>
<Route path= '/request' exact>
<RequestMenu />
<FindAllReceivedRequests />
<section style = {{ marginTop: '5rem',
}}>
<FindAllGivenConsents />
</section>
</Route>
<Route path= '/givenrequest' exact>
<RequestMenu />
<FindAllGivenRequests />
<section style = {{ marginTop: '5rem',
}}>
<FindAllReceivedConsents />
</section>
</Route>
<Route path= '/transfer-data' exact>
<ReadConsent />
</Route>
<Route path= '/partner-request' exact>
<NewPartnerRequest />
</Route>
<Route path= '*'>
<NotFound />
</Route>
</Switch>
</Suspense>
</Layout>
<Footer />
</BrowserRouter>
);
}
export default App;
Here is my FindAllMetadata.js where I am fetching allMetadata ( it is working ):
import React, { useState, useEffect, useMemo } from 'react';
import AllMetadataTable from '../data/AllMetadataTable';
import LoadingSpinner from '../UI/LoadingSpinner';
import styles from '../UI/Messages.module.css';
import styled from '../style/Form.module.css';
import { readAllMetadata } from '../lib/api';
const FindAllMetadata = () => {
const [allMetadata, setAllMetadata] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [enteredMetadataFilter, setEnteredMetadataFilter] = useState('all');
// When page is loaded immediately fetch (and display) all metadata (only running the effect when enteredMetadataFilter changes)
useEffect(() => {
// fetch metadata by entered request filter (all or my)
const readAllMetadataHandler = async () => {
setIsLoading(true);
setError(null);
try {
const loadedAllMetadata = await readAllMetadata(enteredMetadataFilter);
setAllMetadata(loadedAllMetadata);
} catch (error) {
setError(error);
}
setIsLoading(false);
};
readAllMetadataHandler();
}, [enteredMetadataFilter]);
// display fetched content
const content = useMemo(() => {
if (error) {
return <div className={styles.negative}> { error.message } </div>;
} else if (isLoading) {
return <section style = {{margin : '1rem 17rem' }} ><LoadingSpinner /> </section>;
} else {
return (
<AllMetadataTable allMetadata = { allMetadata }
metadataFilter = { enteredMetadataFilter }
issLoading = { isLoading }
/>
);
}
}, [isLoading, error, allMetadata, enteredMetadataFilter]);
return (
<>
{/** pick filter for displaying metadata */}
{!isLoading &&
<section style= {{ marginLeft : '-10rem'}} >
<select className={styled.selectControl}
onChange={ event => {
setEnteredMetadataFilter(event.target.value);
}} >
<option value='' disabled style={{ color: '#cccccc' }} > Choose an option
</option>
<option value = 'all'> All Metadata </option>
<option value = 'my'> My Data </option>
</select>
</section>
}
<section>
{/**display content by status: error, loading, allmetadata, mymetadata */}
{ content }
</section>
</>
)
}
export default FindAllMetadata;
Here is my AllMetadataTable.js component where I am displaying fetched metadata in a table ( it is working and when I click + button it is redirecting me to correct URL ) :
import React from 'react';
import { Table, Button } from 'semantic-ui-react';
import "semantic-ui-css/components/table.min.css";
//import Metadata from './Metadata';
import classes from '../style/Form.module.css';
import Time from '../time/time';
import { useHistory } from 'react-router-dom';
import Metadata from './Metadata';
const AllMetadataTable = ({ allMetadata, metadataFilter, issLoading }) => {
const history = useHistory();
// sorted by time created - newest first
const allMetadataSorted = [...allMetadata].sort((a, b) => {
return new Date(b.TimestampCreated) - new Date(a.TimestampCreated);
});
// open details page for wanted metadata
const openDetailsPage = (key) => {
history.push({
pathname: 'data',
search: `?id=${allMetadata[key].DObjectId}`
})
};
return (
<>
{!issLoading &&
<Table celled fixed singleLine
style={{
width : '60rem',
marginLeft: '-10rem',
}} >
<Table.Header>
<Table.Row>
<Table.HeaderCell>Creator</Table.HeaderCell>
<Table.HeaderCell>Host</Table.HeaderCell>
<Table.HeaderCell>Domain</Table.HeaderCell>
<Table.HeaderCell>Format</Table.HeaderCell>
<Table.HeaderCell>Time Created</Table.HeaderCell>
<Table.HeaderCell
style={{
width : '4rem',
}}>Details</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{allMetadataSorted.map((metadata) => (
<React.Fragment key={metadata.key}>
<Table.Row>
<Table.Cell>{metadata.OrgIdCreator}</Table.Cell>
<Table.Cell>{metadata.OrgIdHost}</Table.Cell>
<Table.Cell>{metadata.TagsDomain}</Table.Cell>
<Table.Cell>{metadata.DataFormatId}</Table.Cell>
<Table.Cell>{Time(metadata.TimestampCreated)}</Table.Cell>
<Table.Cell>
{/** open/close metadata */}
<Button className={classes.uichange}
style ={{
border: 'none',
borderRadius: '0px',
color: 'white',
cursor: 'pointer',
backgroundColor: '#19a47c',
margin: '0 1rem',
fontSize : 22 }}
onClick={() => openDetailsPage(metadata.key) }>
+
</Button>
</Table.Cell>
</Table.Row>
</React.Fragment>
))}
</Table.Body>
</Table>
}
</>
);
};
export default AllMetadataTable;`
Here is my Metadata.js component which I wanna show in a new page when + button in a table is clicked ( id I am getting is corrrect and it is displaying in a list correctly but all other fields are empty; how can I access other fields and display them ?) :
`import React from 'react';
import classes from '../style/SingleData.module.css';
import list from '../style/List.module.css';
import { Button } from 'semantic-ui-react';
//import styles from '../UI/Messages.module.css';
import LoadingSpinner from '../UI/LoadingSpinner';
import Time from '../time/time';
import { useLocation } from 'react-router-dom';
/** import ORG_NAME */
const ORG = process.env.REACT_APP_ORG_NAME;
const Metadata = (props) => {
const { search } = useLocation();
const id = new URLSearchParams(search).get('id');
console.log(id);
// close metadata
const stopReadingDataHandler = () => {
props.onClose()
};
return (
<>
<ul className={list.tableList} >
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong> Data Id: </strong> {id}
</li>
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong> Doc Type Code: </strong> {props.DocTypeCode}
</li>
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong> Data Format: </strong> {props.DataFormatId}
</li>
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong>Creator: </strong> {props.OrgIdCreator}
</li>
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong> Host: </strong> {props.OrgIdHost}
</li>
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong>Tags Content: </strong> {props.TagsContent}
</li>
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong>Domain: </strong> {props.TagsDomain}
</li>
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong>Time Created: </strong> {Time(props.TimestampCreated)}
</li>
<li style={{ borderRadius: '0px' }} className={classes.data}>
<strong>Time Updated: </strong> {Time(props.TimestampUpdated)}
</li>
{ /** display Cancel button if you are Creator or Host */}
{!props.isLoading && (props.OrgIdCreator === ORG || props.OrgIdHost === ORG) && props.transferCheckStatus === false ?
<div style={{ justifyContent: 'flex-start' }}
className={classes.Form__actions}>
<Button className={classes.uichangedelete}
style ={{
border: 'none',
borderRadius: '3px',
color: 'white',
cursor: 'pointer',
backgroundColor: 'red',
margin: '10px',
fontSize : 22 }}
type= 'button'
content='Cancel'
onClick={ stopReadingDataHandler }
/>
</div>
: null }
{/** display loading spinner if loading */}
{props.isLoading && <LoadingSpinner />}
</ul>
</>
);
};
export default Metadata;
I tried using props inside FindAllMetadata, inside AllMetadataTable; I created other page Details.js in same folder as FindAllMetadata ( pages folder ) ; I tried useHistory, useLocation, useParams etc. `
In your openDetailsPage function you are passing only the id to the Metadata component:
const openDetailsPage = (key) => {
history.push({
pathname: 'data',
search: ?id=${allMetadata[key].DObjectId}
})
};
You are using history.push method with the following parameters:
pathname => which is '/data/ for Metadata component
search => query to url (NOTE: Here you are passing only the id)
Try adding:
state => an object to pass to the Metadata components:
history.push({
pathname: 'data',
search: `?id=${allMetadata[key].DObjectId}`,
state: {item: allMetadata[key]}
})
Then access it on the Metadata component by using:
props.location.state.item

Redirect wrong pages and url

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>
);
};

Commerce JS, generateToken returning "Material-UI: A component is changing the controlled value state of Select to be uncontrolled."

This is where i generate the token
import React, { useState, useEffect } from 'react';
import { Paper, Stepper, Step, StepLabel, Typography, CircularProgress, Divider, Button } from '#material-ui/core';
import { commerce } from '../../../lib/commerce';
import useStyles from './styles';
import AddressForm from '../AddressForm';
import PaymentForm from '../PaymentForm';
const steps = ['Shipping address', 'Payment details'];
const Checkout = ({ cart }) => {
const [activeStep, setActiveStep] = useState(0);
const [checkoutToken, setCheckoutToken] = useState(null);
const classes = useStyles();
useEffect(() => {
if (cart.id) {
const generateToken = async () => {
try {
const token = await commerce.checkout.generateToken(cart.id, { type: 'cart' });
setCheckoutToken(token)
} catch (error){
console.log(error);
}
};
generateToken();
}
}, [cart]);
const Confirmation = () => (
<div>
Confirmation
</div>
)
const Form = () => activeStep === 0
? <AddressForm checkoutToken={checkoutToken} />
: <PaymentForm />
return (
<>
<div className={classes.toolbar} />
<main className={classes.layout} >
<Paper className={classes.paper}>
<Typography variant='h4' align='center'>Checkout</Typography>
<Stepper activeStep={activeStep} className={classes.stepper}>
{steps.map((step) => (
<Step key={step}>
<StepLabel>{step}</StepLabel>
</Step>
))}
</Stepper>
{activeStep === steps.length ? <Confirmation /> : checkoutToken && <Form />}
</Paper>
</main>
</>
)
}
export default Checkout
Here is my App.js
import React, { useState, useEffect, Fragment } from 'react'
import { commerce } from './lib/commerce';
import { Products, Navbar, Cart, Checkout } from './components';
import { BrowserRouter as Router, Routes, Route} from 'react-router-dom';
const App = () => {
const [products, setProducts] = useState([]);
const [cart, setCart] = useState({});
const fetchProducts = async () => {
const { data } = await commerce.products.list();
setProducts(data);
}
const fetchCart = async () => {
setCart(await commerce.cart.retrieve())
}
const handleAddToCart = async ( productId, quantity) =>{
const { cart } = await commerce.cart.add(productId, quantity);
setCart(cart);
}
const handleUpdateCartQty = async (productId, quantity) => {
const { cart } = await commerce.cart.update(productId, { quantity });
setCart(cart);
}
const handleRemoveFromCart = async (productId) => {
const { cart } = await commerce.cart.remove(productId);
setCart(cart);
}
const handleEmptyCart = async () => {
const { cart } = await commerce.cart.empty();
setCart(cart);
}
useEffect(() => {
fetchProducts();
fetchCart();
}, []);
return (
<Router>
<div>
<Navbar totalItems={cart.total_items} />
<Routes>
<Route exact path='/' element={<Products products={products} onAddToCart={handleAddToCart} />} />
<Route exact path='/cart' element={<Cart cart={cart} handleUpdateCartQty={handleUpdateCartQty} handleAddToCart={handleAddToCart} handleRemoveFromCart={handleRemoveFromCart} handleEmptyCart={handleEmptyCart} />} />
<Route exact path='/checkout' element={ <Checkout cart={cart} />} />
</Routes>
</div>
</Router>
)
}
export default App;
And here is my cart.jsx incase their is anything relevant there
import React from 'react'
import { Container, Typography, Button, Grid} from '#material-ui/core';
import { Link } from 'react-router-dom';
import useStyles from './styles';
import CartItem from './CartItem/CartItem';
const Cart = ({ cart, handleUpdateCartQty, handleRemoveFromCart, handleEmptyCart }) => {
const classes = useStyles();
const EmptyCart = () => (
<Typography variant='subtitle1'>
You have no items in your shopping cart.
<Link to='/' className={classes.link}>Add Items!</Link>
</Typography>
);
const FilledCart = () => (
<>
<Grid container spacing={3}>
{ cart.line_items.map((item) => (
<Grid item xs={12} sm={4} key={item.id}>
<CartItem item={item} onUpdateCartQty={handleUpdateCartQty} onRemoveFromCart={handleRemoveFromCart} />
</Grid>
))}
</Grid>
<div className={classes.cardDetails}>
<Typography variant='h4'>
Subtotal: {cart.subtotal.formatted_with_symbol}
<div>
<Button className={classes.emptyButton} size='large' type='button' variant='contained' color='secondary' onClick={handleEmptyCart}>
Empty Cart
</Button>
<Button component={Link} to='/checkout' className={classes.checkoutButton} size='large' type='button' variant='contained' color='primary'>
Checkout
</Button>
</div>
</Typography>
</div>
</>
);
// Wait for cart to load items
if(!cart.line_items){
return '...loading';
}
return (
<Container>
<div className={classes.toolbar} />
<Typography className={classes.title} varaint='h3' gutterBottom >Your Shopping Cart</Typography>
{ !cart.line_items.length ? <EmptyCart /> : <FilledCart />}
</Container>
)
}
export default Cart
[error messages][1]
[1]: https://i.stack.imgur.com/vlard.png
Warning: Expected onSubmit listener to be a function, instead got a
value of string type. form
FormProvider#http://localhost:3000/static/js/bundle.js:76722:7
AddressForm#http://localhost:3000/static/js/bundle.js:1096:7 Form div
Paper#http://localhost:3000/static/js/bundle.js:12332:17
WithStyles#http://localhost:3000/static/js/bundle.js:19639:25 main
Checkout#http://localhost:3000/static/js/bundle.js:1332:7
Routes#http://localhost:3000/static/js/bundle.js:67209:7 div
Router#http://localhost:3000/static/js/bundle.js:67146:7
BrowserRouter#http://localhost:3000/static/js/bundle.js:65952:7
App#http://localhost:3000/static/js/bundle.js:347:82
Warning: A component is changing a controlled input to be
uncontrolled. This is likely caused by the value changing from a
defined to undefined, which should not happen. Decide between using a
controlled or uncontrolled input element for the lifetime of the
component. More info: https://reactjs.org/link/controlled-components
input SelectInput#http://localhost:3000/static/js/bundle.js:13482:19
div InputBase#http://localhost:3000/static/js/bundle.js:8257:25
WithStyles#http://localhost:3000/static/js/bundle.js:19639:25
Input#http://localhost:3000/static/js/bundle.js:9146:26
WithStyles#http://localhost:3000/static/js/bundle.js:19639:25
Select#http://localhost:3000/static/js/bundle.js:13182:26
WithStyles#http://localhost:3000/static/js/bundle.js:19639:25 div
Grid#http://localhost:3000/static/js/bundle.js:7352:29
WithStyles#http://localhost:3000/static/js/bundle.js:19639:25 div
Grid#http://localhost:3000/static/js/bundle.js:7352:29
WithStyles#http://localhost:3000/static/js/bundle.js:19639:25 form
FormProvider#http://localhost:3000/static/js/bundle.js:76722:7
AddressForm#http://localhost:3000/static/js/bundle.js:1096:7 Form div
Paper#http://localhost:3000/static/js/bundle.js:12332:17
WithStyles#http://localhost:3000/static/js/bundle.js:19639:25 main
Checkout#http://localhost:3000/static/js/bundle.js:1332:7
Routes#http://localhost:3000/static/js/bundle.js:67209:7

Pagination is not working in React Frontend

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.

React music player

I want to create a music player on a website. The Ideea is to choose a song and play it automaticly. The song must play on all pages and I need an play/pause button.
I have created all the componentns but I have a bug. When I'm on the main page with the player component, the play/pause button does not work properly, If I stop the music I can't start it again, it works only on another pages. Here is the website https://thebrandbar.studio/#/
App.js
import React, { useState } from 'react';
import { HashRouter as Router, Route, Switch } from "react-router-dom";
import ScrollToTop from "./helper/scrollToTop";
import Home from "./pages/Home";
import Projects from "./pages/Projects";
import Team from "./pages/Team";
import ProjectPage from "./pages/ProjectPage";
import Error from "./pages/Error";
import TermsOfUse from "./pages/TermsOfUse";
import PrivacyPolicy from "./pages/PrivacyPolicy";
import Cookies from "./pages/Cookies";
const App = () => {
const [currentTrackIndex, setCurrentTrackIndex] = useState(null);
const [trackURL, setTrackURL] = useState('');
const [playing, setPlaying] = useState(false);
const callbackFunction = (currentTrackIndex, trackURL, playing) => {
setCurrentTrackIndex(currentTrackIndex);
setTrackURL(trackURL);
setPlaying(playing);
};
const player = document.getElementById('player');
const onPlayPauseClickHandler = (event) => {
setPlaying(!playing);
if (!playing) {
player.play();
} else {
player.pause();
}
}
const renderPlayBtn = () => {
if (currentTrackIndex == null) {
return;
} else {
return <div className="play-btn">
<p onClick={onPlayPauseClickHandler} className={`play ${playing ? "red-bg" : "blue-bg"}`}>
{playing ? "SOUND OFF" : "SOUND ON"}
</p>
</div>
}
}
return (
<>
<Router>
<ScrollToTop />
<Switch>
<Route exact path={`${process.env.PUBLIC_URL + '/'}`} >
<Home parentCallback={callbackFunction} player={player}/>
</Route>
<Route
path={`${process.env.PUBLIC_URL + '/projects'}`}
component={Projects}
/>
<Route
path={`${process.env.PUBLIC_URL}/project/:projectId`}
component={ProjectPage}
/>
<Route
path={`${process.env.PUBLIC_URL + '/team'}`}
component={Team}
/>
<Route
path={`${process.env.PUBLIC_URL + '/terms'}`}
component={TermsOfUse}
/>
<Route
path={`${process.env.PUBLIC_URL + '/privacy'}`}
component={PrivacyPolicy}
/>
<Route
path={`${process.env.PUBLIC_URL + '/cookies'}`}
component={Cookies}
/>
<Route exact component={Error} />
</Switch>
</Router>
<audio id="player" src={trackURL} type="audio/mpeg"></audio>
{
renderPlayBtn()
}
</>
);
};
export default App;
The main page
import React, { useState, useEffect } from 'react';
import Loader from "../container/Loader";
import { Helmet } from "react-helmet";
import Cookies from "../components/cookies";
import LayoutDefault from "../container/LayoutDefault";
import Header from "../components/header/Header";
import HeroArea from "../container/Hero";
import MusicPlayer from "../container/MusicPlayer";
import FeaturedProjects from "../container/FeaturedProjects";
import Contact from "../container/Contact";
import Footer from "../container/Footer";
const Home = ({ parentCallback, player }) => {
const [currentTrackIndex, setCurrentTrackIndex] = useState(null);
const [trackURL, setTrackURL] = useState('');
const [playing, setPlaying] = useState(false);
const callbackFunction = (currentTrackIndex, trackURL, playing) => {
setCurrentTrackIndex(currentTrackIndex);
setTrackURL(trackURL);
setPlaying(playing);
};
useEffect(() => {
parentCallback(currentTrackIndex, trackURL, playing);
});
return (
<Loader>
<Helmet>
<title>TheBrandBar</title>
</Helmet>
<Cookies />
<LayoutDefault className="template-color-2 bg_color--4">
<Header />
<HeroArea />
<MusicPlayer parentCallback={callbackFunction} player={player}/>
<FeaturedProjects />
<Contact />
<Footer />
</LayoutDefault>
</Loader>
);
};
export default Home;
and Music Player component
import React, { useState, useEffect } from "react";
import { Container, Row, Col } from "react-bootstrap";
import DB from '../data/music/music.js';
const Player = ({ parentCallback }) => {
const [tracksList] = useState(DB);
const [currentTrackIndex, setCurrentTrackIndex] = useState(null);
const [trackID, setTrackID] = useState(null);
const [trackURL, setTrackURL] = useState('');
const [playing, setPlaying] = useState(false);
useEffect(() => {
parentCallback(currentTrackIndex, trackURL, playing);
});
const selectThisTrack = (event, trackID) => {
let currentTrackIndex = 0;
tracksList.map((track, index) => {
if (track.id === trackID) {
currentTrackIndex = index;
}
return track;
});
setCurrentTrackIndex(currentTrackIndex);
setTrackID(tracksList[currentTrackIndex].id);
setTrackURL(require(`../assets/player/music/${currentTrackIndex + 1}.mp3`));
setPlaying(true);
const player = document.getElementById('player');
player.src = trackURL;
player.preload = true;
player.autoplay = true;
player.loop = true;
if (playing) {
player.play();
} else {
player.pause();
}
}
const renderCover = () => {
if (!playing) {
return <img className="img-cover-default" src={require(`../assets/player/covers/default.gif`)} alt="" />
} else {
return <img className="img-cover" src={require(`../assets/player/covers/${currentTrackIndex + 1}.gif`)} alt="" />
}
}
return (
<>
<Container>
<Row>
<Col className="play-list" xs={{ span: 12, order: 2 }} lg={{ span: 4, order: 1 }}>
<p className="your-rythm ">WHAT'S YOUR RYTHM?</p>
<br />
{DB.map((track, index) => (
<div
key={track.id}
index={index}
className={`song ${track.id === trackID ? "selected" : ""}`}
id={track.id === trackID ? "activeTrack" : ""}
onClick={(ev) => selectThisTrack(ev, track.id)}
>
<p>{track.title}</p>
</div>
))}
</Col>
<Col xs={{ span: 12, order: 1 }} lg={{ span: 8, order: 2 }}>
<div className="song-cover">
{
renderCover()
}
</div>
</Col>
</Row>
</Container>
</>
);
};
export default Player;
Thanks! :)
I think the problem is here:
const player = document.getElementById('player');
const onPlayPauseClickHandler = (event) => {
setPlaying(!playing);
if (!playing) {
player.play();
} else {
player.pause();
}
}
React doesn't update right after set* is called. Instead, you have to use useEffect to do play/pause.
Remove
if (!playing) {
player.play();
} else {
player.pause();
}
and use it in useEffect.
useEffect(() => {
!playing ? player.play() : player.pause();
}, [playing]);
EDIT
Place the useEffect here:
const App = () => {
const [currentTrackIndex, setCurrentTrackIndex] = useState(null);
const [trackURL, setTrackURL] = useState('');
const [playing, setPlaying] = useState(false);
const callbackFunction = (currentTrackIndex, trackURL, playing) => {
setCurrentTrackIndex(currentTrackIndex);
setTrackURL(trackURL);
setPlaying(playing);
};
const player = document.getElementById('player');
const onPlayPauseClickHandler = (event) => {
setPlaying(!playing);
}
const renderPlayBtn = () => {
if (currentTrackIndex == null) {
return;
} else {
return <div className="play-btn">
<p onClick={onPlayPauseClickHandler} className={`play ${playing ? "red-bg" : "blue-bg"}`}>
{playing ? "SOUND OFF" : "SOUND ON"}
</p>
</div>
}
}
// PLACE IT HERE
useEffect(() => {
!playing ? player.play() : player.pause();
}, [playing]);
return (
<>
<Router>
<ScrollToTop />
<Switch>
<Route exact path={`${process.env.PUBLIC_URL + '/'}`} >
<Home parentCallback={callbackFunction} player={player}/>
</Route>
<Route
path={`${process.env.PUBLIC_URL + '/projects'}`}
component={Projects}
/>
<Route
path={`${process.env.PUBLIC_URL}/project/:projectId`}
component={ProjectPage}
/>
<Route
path={`${process.env.PUBLIC_URL + '/team'}`}
component={Team}
/>
<Route
path={`${process.env.PUBLIC_URL + '/terms'}`}
component={TermsOfUse}
/>
<Route
path={`${process.env.PUBLIC_URL + '/privacy'}`}
component={PrivacyPolicy}
/>
<Route
path={`${process.env.PUBLIC_URL + '/cookies'}`}
component={Cookies}
/>
<Route exact component={Error} />
</Switch>
</Router>
<audio id="player" src={trackURL} type="audio/mpeg"></audio>
{
renderPlayBtn()
}
</>
);
};
export default App;

Categories

Resources