Link to favorites page not working in react
Here is the code for my navbar
The fav button is found under menu icons the first one.
I have it in a link and then the nav item icon inside this link
import React, { useState, useEffect, useRef, useContext } from "react";
import "./Navbar.css";
import "../App.css";
import { CSSTransition } from "react-transition-group";
import { ReactComponent as HeartIcon } from "../icons/heart.svg";
import { ReactComponent as CartIcon } from "../icons/cart.svg";
import { ReactComponent as AccountIcon } from "../icons/account.svg";
import { ReactComponent as RightArrowIcon } from "../icons/rightArrow.svg";
import { ReactComponent as LeftArrowIcon } from "../icons/leftArrow.svg";
import { ReactComponent as OrdersIcon } from "../icons/orders.svg";
import { ReactComponent as SettingIcon } from "../icons/setting.svg";
import { ReactComponent as DarkModeIcon } from "../icons/darkMode.svg";
import { ReactComponent as LocationIcon } from "../icons/location.svg";
import { ReactComponent as CurrencyIcon } from "../icons/currency.svg";
import logo from "../logo/tryb_logo_medium.png";
import { Link, Route, Router } from "react-router-dom";
import { Button, Div, Icon, SideDrawer, Text } from "atomize";
import { Dropdown } from "react-bootstrap";
//Cart
import { Container, Anchor } from 'atomize'
import { ShopContext } from '../context/shopContext'
import "../context/AuthContext";
import fire from "../config/fire";
import Login from "./Login";
import Cart from './../components/Cart';
import { createGlobalStyle } from "styled-components";
import { Label,Switch } from "atomize";
function Nav() {
//Use fucntion sopen cart from shopConext
const { openCart, checkout } = useContext(ShopContext)
return (
<Navbar>
<Cart />
{/* LOGO */}
<Link to="/">
<img className="_navbar-logo" src={logo} />
</Link>
{/* Hamburger Menu */}
<div onClick="" className="menu-btn">
<div className="menu-btn__burger"></div>
</div>
<div className="menu-items">
<Link to="/new-in">New In</Link>
<Link to="/prints">Prints</Link>
<Link to="/bestsellers">Bestsellers</Link>
<Link to="/inspiration">Inspiration</Link>
</div>
{/* Menu Icons */}
<Link to="/favorites">
<NavItem class="hide-icons" icon={<HeartIcon class="icon" />} />
</Link>
{/* Changes for shopping cart count */}
<li className="_nav-item" onClick={() => openCart()}>
<a href="#" className="icon-button">
<CartIcon class="icon" id="cart" />
<span className="cart-counter">{checkout.lineItems?.length || 0}</span>
</a>
</li>
<NavItem icon={<AccountIcon class="icon" />}>
<DropdownMenu>Test</DropdownMenu>
</NavItem>
</Navbar >
);
}
function Navbar(props) {
return (
<nav className="_navbar">
<ul className="_navbar-buttons">{props.children}</ul>
</nav>
);
}
function NavItem(props) {
const [open, setOpen] = useState(false);
return (
<li className="_nav-item">
<div className="icon-button" onClick={() => setOpen(!open)}>
{props.icon}
</div>
{open && props.children}
</li>
);
}
//dropdown menu for navbar
function DropdownMenu() {
const [activeMenu, setActiveMenu] = useState("main");
const [menuHeight, setMenuHeight] = useState(null);
const dropdownRef = useRef(null);
const [open, setOpen] = useState(false);
useEffect(() => {
setMenuHeight(dropdownRef.current?.firstChild.offsetHeight);
}, []);
function calcHeight(el) {
const height = el.offsetHeight;
setMenuHeight(height);
}
function DropdownItem(props) {
return (
<div
className="menu-item"
onClick={() => props.goToMenu && setActiveMenu(props.goToMenu)}
>
<span className="icon-button">{props.leftIcon}</span>
{props.children}
<span className="icon-right">{props.rightIcon}</span>
</div>
);
}
const [user, setUser] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [emailError, setEmailError] = useState("");
const [passwordError, setPasswordError] = useState("");
const [hasAccount, setHasAccount] = useState("");
//Logout
const handleLogout = () => {
fire.auth().signOut();
};
const authListener = () => {
fire.auth().onAuthStateChanged((user) => {
if (user) {
setUser(user);
} else {
setUser("");
}
});
};
useEffect(() => {
authListener();
}, []);
return (
<>
<div className="dropdown" style={{ height: menuHeight }} ref={dropdownRef} >
<CSSTransition
in={activeMenu === "main"}
timeout={500}
classNames="menu-primary"
unmountOnExit
onEnter={calcHeight}
>
<div className="menu">
<DropdownItem
leftIcon={<AccountIcon class="icon" />}
rightIcon={<RightArrowIcon class="icon" />}
goToMenu="my-account"
>
<a > My Account</a>
</DropdownItem>
<DropdownItem leftIcon={<OrdersIcon class="icon" />}>
My Orders
</DropdownItem>
<DropdownItem
leftIcon={<SettingIcon class="icon" />}
goToMenu="settings"
className="dropdown"
>
Settings
</DropdownItem>
</div>
</CSSTransition>
{/* Settings Menu */}
<CSSTransition
in={activeMenu === "settings"}
timeout={500}
classNames="menu-secondary"
unmountOnExit
onEnter={calcHeight}
>
<div className="menu">
<DropdownItem
goToMenu="main"
leftIcon={<LeftArrowIcon class="icon" />}
>
<h2>Settings</h2>
</DropdownItem>
<DropdownItem leftIcon={<LocationIcon class="icon" />}>
Location
</DropdownItem>
<DropdownItem leftIcon={<CurrencyIcon class="icon" />}>
Currency
</DropdownItem>
</div>
</CSSTransition>
{/* My Account Menu */}
<CSSTransition
in={activeMenu === "my-account"}
timeout={500}
classNames="menu-secondary"
unmountOnExit
onEnter={calcHeight}
>
<div>
<DropdownItem
goToMenu="main"
leftIcon={<LeftArrowIcon class="icon" />}
>
<h2>My Account</h2>
</DropdownItem>
{/*
<Link to="/account">
<DropdownItem leftIcon="">
Account
</DropdownItem></Link> */}
{user ? (
<>
<span>
<Link to="/account">
<DropdownItem leftIcon="">Account</DropdownItem>
</Link>
<Link to="/" onClick={handleLogout} >
<DropdownItem>Logout</DropdownItem>
</Link>
</span>
</>
) : (
<>
<span>
<Link to="/login" onClick={() => setOpen(!open)}>
<DropdownItem>Login</DropdownItem>
</Link>
</span>
</>
)}
</div>
</CSSTransition>
</div></>
);
}
export { Nav };
Here is my favorites page
import React, { useContext, useState } from "react";
import { Text, Button, Row, Col, Container, Image, ThemeProvider } from "atomize";
import { ShopContext } from "../../context/shopContext";
const theme = {
grid: {
colCount: 8,
gutterWidth: 0
}
};
const FavoritesPage = () => {
const [favorites, setFavorites] = useState(JSON.parse(localStorage.getItem("favorites") || "[]"));
const { addItemToCheckout } = useContext(
ShopContext
);
const favoritesList = favorites.map(product => (
<Container>
<ThemeProvider theme={theme}>
<Row bg="black" rounded="lg" d="flex"
m="6rem">
<Col size={{ xs: 8, md:5, lg: 5 }}>
<Image src={product.images[0].src} w="20rem" p="2rem"/>
</Col>
<Col align="space-around" >
<Text tag="h1" textColor="white" textWeight="200" m={{ y: "2rem" }} >
{product.title}
</Text>
<Text tag="h3" textColor="white" m={{ y: "2rem" }} textWeight="200">
€ {product.variants[0].price}
</Text>
<Button
rounded="lg"
shadow="3"
bg="black500"
m={{ y: "2rem" }}
onClick={() => addItemToCheckout(product.variants[0].id, 1)}
>Add to cart
</Button>
</Col>
</Row>
</ThemeProvider>
</Container>
))
return favoritesList;
};
export default FavoritesPage;
It wont load the fav component any thoughts greatly appreciated thanks
anything else that may be needed please ask thanks
Related
I wanted to create an interactive and attractive navigation bar, and from the tutorials I've followed, it seems as though React Router is unable to be incorporated.
import './navbar.css';
import { ReactComponent as BellIcon } from './icons/bell.svg';
import { ReactComponent as CaretIcon } from './icons/caret.svg';
import { ReactComponent as ChevronIcon } from './icons/chevron.svg';
import { ReactComponent as ArrowIcon } from './icons/arrow.svg';
import { ReactComponent as DiscordIcon } from './icons/Discord.svg';
import { ReactComponent as BookIcon } from './icons/book-solid.svg';
import { ReactComponent as GoalIcon } from './icons/bullseye-solid.svg';
import { ReactComponent as CoinsIcon } from './icons/coins-solid.svg';
import { ReactComponent as ScrollIcon } from './icons/scroll-solid.svg';
import { ReactComponent as GavelIcon } from './icons/gavel-solid.svg';
import { ReactComponent as SocialIcon } from './icons/user-solid.svg';
import { ReactComponent as InstagramIcon } from './icons/instagram-brands.svg';
import { ReactComponent as RedditIcon } from './icons/reddit-alien-brands.svg';
import { ReactComponent as SpotifyIcon } from './icons/spotify-brands.svg';
import { ReactComponent as SoundCloudIcon } from './icons/soundcloud-brands.svg';
import { ReactComponent as MusicIcon } from './icons/headphones-solid.svg';
import { ReactComponent as HandIcon } from './icons/hand-sparkles-solid.svg';
import { ReactComponent as ForteIcon } from './icons/fortelogo.svg';
import React, { useState, useEffect, useRef } from 'react';
import { CSSTransition } from 'react-transition-group';
import GetInvolved from '../pages/getinvolved';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';
function NavbarFinal() {
return (
<Navbar>
<NavLogo icon={<ForteIcon />} />
<NavItem icon={<BellIcon />}>
</NavItem>
<NavItem icon={<DiscordIcon />}>
<DiscordLink/>
</NavItem>
<NavItem icon={<CaretIcon />}>
<DropdownMenu></DropdownMenu>
</NavItem>
</Navbar>
);
}
function Navbar(props) {
return (
<nav className="navbar">
<ul className="navbar-nav">{props.children}</ul>
</nav>
);
}
function NavItem(props) {
const [open, setOpen] = useState(false);
return (
<li className="nav-item">
<a href="#" className="icon-button" onClick={() => setOpen(!open)}>
{props.icon}
</a>
{open && props.children}
</li>
);
}
function NavLogo(props) {
const [open, setOpen] = useState(false);
return (
<li className="logo-item">
<a href="#" className="logo-item" onClick={() => setOpen(!open)}>
{props.icon}
</a>
{open && props.children}
</li>
);
}
function DiscordLink () {
window.location.href="https://discord.gg/VCCPMBugKZ";
}
function DropdownMenu() {
const [activeMenu, setActiveMenu] = useState('main');
const [menuHeight, setMenuHeight] = useState(null);
const dropdownRef = useRef(null);
useEffect(() => {
setMenuHeight(dropdownRef.current?.firstChild.offsetHeight)
}, [])
function calcHeight(el) {
const height = el.offsetHeight;
setMenuHeight(height);
}
function DropdownItem(props) {
return (
<a href="#" className="menu-item" onClick={() => props.goToMenu && setActiveMenu(props.goToMenu)}>
<span className="icon-button">{props.leftIcon}</span>
{props.children}
<span className="icon-right">{props.rightIcon}</span>
</a>
);
}
function DropdownItem1(props) {
return (
<Link to component= {<GetInvolved />} className="menu-item">
<span className="icon-button">{props.leftIcon}</span>
{props.children}
<span className="icon-right">{props.rightIcon}</span>
</Link>
);
}
return (
<div className="dropdown" style={{ height: menuHeight }} ref={dropdownRef}>
<CSSTransition
in={activeMenu === 'main'}
timeout={500}
classNames="menu-primary"
unmountOnExit
onEnter={calcHeight}>
<div className="menu">
<DropdownItem
leftIcon={<BookIcon />}
rightIcon={<ChevronIcon />}
goToMenu="about">
About
</DropdownItem>
<DropdownItem
leftIcon= {<SocialIcon />}
rightIcon={<ChevronIcon />}
goToMenu="socials">
Socials
</DropdownItem>
<DropdownItem
leftIcon={<MusicIcon />}
rightIcon={<ChevronIcon />}
goToMenu="music">
Music
</DropdownItem>
<DropdownItem1
leftIcon = {<HandIcon/>}
onClick={ <GetInvolved/>}>
Get Involved
</DropdownItem1>
</div>
</CSSTransition>
<CSSTransition
in={activeMenu === 'about'}
timeout={500}
classNames="menu-secondary"
unmountOnExit
onEnter={calcHeight}>
<div className="menu">
<DropdownItem goToMenu="main" leftIcon={<ArrowIcon />}>
<h2>About</h2>
</DropdownItem>
<DropdownItem leftIcon={<GoalIcon />}>Mission</DropdownItem>
<DropdownItem leftIcon={<CoinsIcon />}>How It Works</DropdownItem>
<DropdownItem leftIcon={<GavelIcon />}>Governance</DropdownItem>
<DropdownItem leftIcon={<ScrollIcon />}>White Paper</DropdownItem>
</div>
</CSSTransition>
<CSSTransition
in={activeMenu === 'socials'}
timeout={500}
classNames="menu-secondary"
unmountOnExit
onEnter={calcHeight}>
<div className="menu">
<DropdownItem goToMenu="main" leftIcon={<ArrowIcon />}>
<h2>Socials</h2>
</DropdownItem>
<DropdownItem leftIcon={<DiscordIcon />}>Discord</DropdownItem>
<DropdownItem leftIcon={<InstagramIcon />}>Instagram</DropdownItem>
<DropdownItem leftIcon={<RedditIcon />}>Reddit</DropdownItem>
</div>
</CSSTransition>
<CSSTransition
in={activeMenu === 'music'}
timeout={500}
classNames="menu-secondary"
unmountOnExit
onEnter={calcHeight}>
<div className="menu">
<DropdownItem goToMenu="main" leftIcon={<ArrowIcon />}>
<h2>Music</h2>
</DropdownItem>
<DropdownItem leftIcon={<SpotifyIcon />}>Spotify</DropdownItem>
<DropdownItem leftIcon={<SoundCloudIcon />}>SoundCloud</DropdownItem>
</div>
</CSSTransition>
</div>
);
}
export default NavbarFinal;
I tried many different variations and am at a loss. My focus is on the items of the dropdown menu. Routes and Route components cannot contain any other components - and this is probably the biggest roadblock I came across when trying to restructure my code. If this doesn't work, I will obviously need to reformat the navbar to something basic, but as this is an independent project and I wanted to learn to code more sophisticated frontends, any help that could help lead me in the right direction to figure this out would be great.
Good day everyone, I am implementing filtering functionality for a price. I have a function that implements this. When I click on the button, the name of the button itself is displayed in my console, and the product itself is not filtered. Tell me, please, what can it be? The screenshots show the console and my code are infected. Help me please.
app.js file where the whole program is located
import Navbar from './components/Navsbar'
import {useState} from "react"
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import "./App.css";
import {ListProduct} from "./ListProduct";
import data from "./service/data";
import {Home} from './Home'
import AppFilter from './components/Filter';
//import Footer from 'rc-table/lib/Footer';
function App() {
const [filter, setFilter] = useState("");
const [info, setInfo] = useState(data)
const [field,setState] = useState([]);
const searchTerm = (items, term,number) => {
let lower = term.toLowerCase();
if (term.length === 0) return items;
return items.filter((item) => {
let itemLower = item.strDrink.toLowerCase()
return itemLower.indexOf(lower)> -1;
});
};
const onUpdateSearch = (term) => {
setFilter(term);
};
const filterPost =(items,field)=>{
switch(field){
case 'moreThen1000':
return items.filter(item=>item.price > 500);
default:
return items
}
}
const onFilterSelect =(field) =>{
setState(field);
console.log(field)
};
const visible = searchTerm(info.drinks, filter)
const viewable = filterPost(info.drinks,field)
return (
<>
<Router>
<Navbar onUpdateSearch={onUpdateSearch} />
<AppFilter filter={field} onFilterSelect={onFilterSelect}/>
<Routes>
<Route exact path='/' element={<Home />} />
<Route exact path="/ListProduct" element={<ListProduct searchTerm = {visible} onFilterSelect={viewable}/>} />
</Routes>
</Router>
</>
);
}
export default App;
appFilter.js file where the buttons are stored
import React from 'react';
import './Filter.css';
import data from "../service/data";
import "bootstrap/dist/css/bootstrap.min.css";
const AppFilter = (props) => {
const buttonsData = [
{name: 'all', label: 'All cocktails'},
{name: 'moreThen1000', label: 'More expensive than 500$'}
];
const buttons = buttonsData.map(({name, label}) => {
const active = props.filter === name;
const clazz = active ? 'btn-light' : 'btn-outline-light';
return (
<button type="button"
className={`btn ${clazz}`}
key={name}
onClick={() => props.onFilterSelect(name)}>
{label}
</button>
)
})
return (
<div className="btn-group">
{buttons}
</div>
)
}
export default AppFilter;
ListProduct.js file where cards with goods are displayed
import "./ListProduct.css";
import "bootstrap/dist/css/bootstrap.min.css";
import { Container, Row, Col, Card } from "react-bootstrap";
export const ListProduct = (props) => {
const {searchTerm, onFilterSelect} = props
const element = searchTerm.map((item, i) => {
const { strDrinkThumb, strDrink, price } = item;
return (
<div className="card">
<li key={i}>
<Container>
<Row>
<Col>
<Card style={{ width: "18rem" }}>
<Card.Img variant="top" src={strDrinkThumb} />
<Card.Body>
<Card.Title>{strDrink}</Card.Title>
<Card.Text>
{ `Alcohol shop . The price is for one glass
${price}$`}
</Card.Text>
</Card.Body>
</Card>
</Col>
</Row>
</Container>
</li>
</div>
);
});
return <div className="site">
<ul>{ element}</ul>
<div>
<footer className="page-footer font-small blue pt-4">
<div className="container-fluid text-center text-md-left">
<div className="row">
<div className="col-md-6 mt-md-0 mt-3">
<h5 className="text-uppercase">Cocktail shop</h5>
<p>Modern cocktail shop for different choices</p>
</div>
<hr className="clearfix w-100 d-md-none pb-0"/>
<div className="col-md-3 mb-md-0 mb-3">
<h5 className="text-uppercase">Our online resources</h5>
<ul className="list-unstyled">
<li>Our instagram page</li>
<li>Our site</li>
</ul>
</div>
</div>
</div>
<div className="footer-copyright text-center py-3">© 2020 Copyright:
MDBootstrap.com
</div>
</footer>
</div>
</div>;
};
I am trying to implement a custom dropdown menu in react, but I am facing some weird issues.
I can't understand why the items in the Services menu don't show up onMouseEnter.
With debugger, the function onMouseEnter gets called, but not able to see list of items
Thanks in advance.
import Dropdown from '../Dropdown'
import React, { useState } from "react";
import { Link } from "react-router-dom";
const Navbar = () => {
const [click, setClick] = useState(false)
const [dropdown, setDropdown] = useState(false)
const handleClick = () => setClick(!click)
const closeMobileMenu = () => setClick(false)
const onMouseEnter = () => {
if (window.innerWidth < 960) {
setDropdown(false)
} else {
setDropdown(true)
}
}
const onMouseLeave = () => {
if (window.innerWidth < 960) {
setDropdown(false)
} else {
setDropdown(false)
}
}
return (
<>
<nav className="nb">
LOGO
<div className='menu-icon' onClick={handleClick}>
<i className={click ? 'fas fa-times' : 'fas fa-bars'}/>
</div>
<ul>
<li
className='nav-item'
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<Link
to='/services'
className='nav-links'
onClick={closeMobileMenu}
>
Services <span className='fas fa-caret-down'></span>
</Link>
{dropdown && <Dropdown />}//here is the problem. I can't see items onMouseEnter
</li>
</ul>
</nav>
</>
)
}
export default Navbar
Here is the Dropdown.js class
import "./Dropdown.css";
import React, { useState } from "react";
import { Link } from "react-router-dom";
const MenuItems = [
{
title: 'Marketing',
path: '/marketing',
cName: 'dropdown-links'
},
]
const Dropdown = () => {
const [click, setClick] = useState(false);
const handleClick = () => setClick(!click);
return (
<>
<ul
onClick={handleClick}
className={click ? "dropdown-menu clicked" : "dropdown-menu"}
>
{MenuItems && MenuItems.map((item, index) => {
return (
<li key={index}>
<Link
className={item.cName}
to={item.path}
onClick={() => setClick(false)}
>
{item.title}
</Link>
</li>
);
})}
</ul>
</>
);
};
export default Dropdown;
you can use these links in index.html so that we have the same icon
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.15.3/css/all.css"
integrity="sha384-SZXxX4whJ79/gErwcOYf+zWLeJdY/qpuqC4cAa9rOGUstPomtqpuNWT9wdPEn2fk"
crossorigin="anonymous"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=PT+Sans:wght#700&display=swap"
rel="stylesheet"
/>
could somone help i'm stuck in such problem with next.js here is my code
this is the error i get in the console
Error: Export encountered errors on following paths:
/admin
/user
in pages in folder named admin/index.js
import Layout from "../../components/Layout";
import Admin from "../../components/auth/Admin";
import Link from "next/link";
const AdminIndex = () => {
return (
<Layout>
<Admin>
<div className="container-fluid">
<div className="row">
<div className="col-md-12 pt-5 pb-5">
<h2>Admin Dashboard</h2>
</div>
<div className="col-md-4">
<ul class="list-group">
<li className="list-group-item">
<Link href="/admin/crud/project">
<a>Create Project</a>
</Link>
</li>
</ul>
</div>
<div className="col-md-8">right</div>
</div>
</div>
</Admin>
</Layout>
);
};
export default AdminIndex;
in folder pages/user/index.js
Error: Export encountered errors on following paths:
/admin
/user
import Layout from "../../components/Layout";
import Private from "../../components/auth/Private";
import Link from "next/link";
const UserIndex = () => {
return (
<Layout>
<Private>
<div className="container-fluid">
<h2>User Dashboard</h2>
</div>
</Private>
</Layout>
);
};
export default UserIndex;
and finally this is my header
import React, { useState } from "react";
import Link from "next/link";
import Router from "next/router";
import nProgress from "nprogress";
import { APP_NAME } from "../config";
import { signout, isAuth } from "../actions/auth";
import {
Collapse,
Navbar,
NavbarToggler,
Nav,
NavItem,
NavLink,
} from "reactstrap";
Router.onRouteChangeStart = (url) => nProgress.start();
Router.onRouteChangeComplete = (url) => nProgress.done();
Router.onRouteChangeError = (url) => nProgress.done();
//next.js giving us the option to use such option
const Header = () => {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => {
setIsOpen(!isOpen);
};
return (
<div>
<Navbar color="light" light expand="md">
<Link href="/">
<NavLink className="font-weight-bold">{APP_NAME}</NavLink>
</Link>
<NavbarToggler onClick={toggle} />
<Collapse isOpen={isOpen} navbar>
<Nav className="ml-auto" navbar>
{!isAuth() && (
<React.Fragment>
<NavItem>
<Link href="/signin">
<NavLink>Signin</NavLink>
</Link>
</NavItem>
<NavItem>
<Link href="/signup">
<NavLink>Signup</NavLink>
</Link>
</NavItem>
</React.Fragment>
)}
{isAuth() && isAuth().role === 0 && (
<NavItem>
<Link href="/user">
<NavLink style={{ cursor: "pointer" }}>
{`${isAuth().name}'s Dashboard`}
</NavLink>
</Link>
</NavItem>
)}
{isAuth() && isAuth().role === 1 && (
<NavItem>
<Link href="/admin">
<NavLink style={{ cursor: "pointer" }}>{`${
isAuth().name
}'s Dashboard`}</NavLink>
</Link>
</NavItem>
)}
{isAuth() && (
<NavItem>
<NavLink
style={{ cursor: "pointer" }}
onClick={() => signout(() => Router.replace(`/signin`))}
>
Signout
</NavLink>
</NavItem>
)}
</Nav>
</Collapse>
</Navbar>
</div>
);
};
export default Header;
I am creating a simple portfolio application for which I require a separate screen for each project from a list of projects. In doing so when I try to get the Id of that project from the URL using match.params.id, it gives a TypeError : Cannot read property 'params' of undefined.
My code ProductScreenById:
import db from '../firebase'
export const ProjectScreenById = ({ match }) => {
const pid = match.params.id
return (
<div>
hello world
</div>
)
}
My ProjectListScreen:
import db from '../firebase'
import { Row, Col, Spinner } from 'react-bootstrap'
import { Project } from '../components/Project'
export const ProjectScreen = () => {
const [projects, setProjects] = useState([])
useEffect(() =>{
db.collection('projects').orderBy('index','asc').onSnapshot(snapShot => {
setProjects(snapShot.docs.map(doc => ({id:doc.id, project:doc.data()})))
})
},[])
const windowWidth = () => {
const { innerWidth:width, innerHeight:height } = window;
return { width, height }
}
return (<>
{projects.length===0 ?
<div className='mt-5 pt-5'>
<Spinner animation='border' style={{ width:100, height:100 }}/>
</div>
: (
<Row style={{ overflowX: 'hidden', width:'100%' }} className='pl-5 pt-5'>
{projects.map(project => (
<Col key={project.project.index} className='mr-2 mb-5'>
<Project
description={project.project.description.split('.')}
title={project.project.title}
features={project.project.features.split('.')}
git={project.project.git}
link={project.project.link}
index={project.project.index}
id={project.id}
stack={project.project.stack}
/>
</Col>
))}
</Row>
)}
</>
)
}
My Project Component:
import React from 'react'
import { Card, Image } from 'react-bootstrap'
import { Link } from 'react-router-dom'
export const Project = ({ description, features, git, index, link, stack, title, id }) => {
const images = [
'./images/ecom/display.png',
'./images/ytclone/display.png',
'./images/calculator/display.png',
'./images/todo/display.png',
'./images/expense/display.png',
' ./images/techS/display.png',
'./images/tictactoe/display.png',
'./images/canvas/display.png',
'./images/linked/display.png'
]
return (
<Card className='py-3 px-5' style={{ height:'100%'}} sm={12}>
<Image src={images[parseInt(index)]} style={{ width:'100%', border:'0.5px ridge rgb(219,219,219)' }} className='image' />
<b>{title}</b>
<div style={{ textAlign:'left' }} className='mb-2' >
<b>Description:</b>
{description.map(d=>(
<li key={description.indexOf(d)}>{d}</li>
))}</div>
<div style={{ textAlign:'left' }} className='mb-2' id='features'>
<b>Features:</b>
{features.map(f=>(
<li key={features.indexOf(f)}>{f}</li>
))}
</div>
<div style={{ textAlign:'left' }} className='mb-2' id='stack'>
<b>Tech Stack:</b>
{stack.map(s=>(
<li key={stack.indexOf(s)}>{s}</li>
))}
</div>
<div style={{ textAlign:'left' }} className='mb-2' id='git' >
<b>Git Repo: </b>
<a href={git.slice(0,5)==='https' ? git : '/projects'} target='_blank'>{git}</a>
</div>
<div style={{ textAlign:'left' }} className='mb-2' id='link' >
<b>Project link: </b>
<a href={link==='Upcoming' || link==='N/A' ? '/projects' : link}>{link}</a>
</div>
<Link to={`/projects/${id}`} className='view'><b>View Project & Project Details</b></Link>
</Card>
)
}
App.js:
import './App.css';
import { ContactScreen } from './screens/ContactScreen'
import { ProjectScreen } from './screens/ProjectScreen'
import { Header } from './components/Header'
import { Footer } from './components/Footer'
import { ProjectScreenById } from './screens/ProjectScreenById'
import { BrowserRouter as Router, Route } from 'react-router-dom'
function App() {
return (
<div className="App">
<Header/>
<Router>
<Route path="/contact" component={ContactScreen} exact/>
<Route path="/projects" component={ProjectScreen} exact />
<Route path="/projects/:id" component={ProjectScreenById} exact/>
</Router>
<Footer/>
</div>
);
}
export default App;
This answer should help you out, but until then, here's a quick hack for it with useLocation:
const location = useLocation()
const ID = location.pathname.split("/projects/")[1]