how to use react routing to switch between pages - reactjs

i am currently building a shopping website . i finished the homepage and i have to make routing for other pages
i have 3 main files: App.js, Menuitem.js (which is to execute props), and Homepage.js (which also is used to apply executing props from sections array which includes titles and background images and sections paths)
this is the App js
import React from "react";
import Homepage from './Homepage'
import "./styles.css";
import './Homepage.css'
import {Route, Switch} from "react-router-dom";
const Hatspage=function() {
return(
<div>
<h1>
Hats page
</h1>
</div>
)
}
function App() {
return (
<div>
<Switch>
<Route exact path='/'component={Homepage}/>
<Route path='/hats'component={Hatspage}/>
</Switch>
</div>
);
}
export default App
Menuitem.js
import React from 'react'
import {WithRouter} from 'react'
const Menuitem= function(props){
return(
<div className='card' style={{ backgroundImage: `url(${props.imageUrl})` }} >
<div className='text-frame'>
<h1 className='title'>{props.title}</h1>
<p className='subtitle'>shop now</p>
</div>
</div>
)
}
export default Menuitem
Homepage.js
import React from "react";
import sections from './directory-components';
import Menuitem from "./menu-item-components";
const arrayOne=[sections.slice(0,3)]
const arrayTwo=[sections.slice(3,)]
function extract(item){
return(
<Menuitem
title={item.title} imageUrl={item.imageUrl}/>
)
}
function Homepage(){
return(
<div className='directory-menu'>
<div className='content'>
{sections.slice(0,3).map(extract) }
</div>
<div className='second'>
{sections.slice(3,).map(extract) }
</div>
</div>
)
}
export default Homepage
so i need for example when i click on hats picture i switch to hats page . how to do that
image attached
Thanks in advance
reactjs routing

You can do two different approaches. Both of them will require an extra prop that will be the actual url you want to access when clicking the menu item.
Assuming you modify your section array to look like this:
[{title: 'Your title', imageUrl: 'your-image.jpg', linkUrl: '/hats'}]
And you modify your extract function to add the url value as a prop in the MenuItem component:
function extract(item){
return(
<Menuitem
title={item.title} imageUrl={item.imageUrl} linkUrl={item.linkUrl} />
)
}
You can do this
First one: Using a Link component from react router:
import React from "react";
import { Link } from "react-router-dom";
const Menuitem= function(props){
return(
<Link to={props.linkUrl}>
<div className='card' style={{ backgroundImage: `url(${props.imageUrl})`
}} >
<div className='text-frame'>
<h1 className='title'>{props.title}</h1>
<p className='subtitle'>shop now</p>
</div>
</div>
</Link>
)
}
Now you will have to add extra styling because that will add a regular a tag, but I like this approach because for example you can open the link in a new tab since it is a regular link.
Using the history prop.
import React from "react";
import { useHistory } from "react-router-dom";
const Menuitem= function(props){
const history = useHistory()
const goToPage = () => history.push(props.linkUrl)
return(
<div className='card' style={{ backgroundImage: `url(${props.imageUrl})`
}} onClick={goToPage} >
<div className='text-frame'>
<h1 className='title'>{props.title}</h1>
<p className='subtitle'>shop now</p>
</div>
</div>
)
}
This approach is a basic on click so if you press the component it will go to the selected page, this will work but keep in mind that event bubbling will be harder if you add more on clicks inside the menu item, so please be aware of that.

You should fire an event inside your MenuItem in order to redirect the user
import { useHistory } from 'react-router-dom'
const history = useHistory()
<img onClick={() => history.push('/hats')} />

Related

React & Typescript Issue: trigger elements with InsertionObserver using props and manage them in other component

Small premise: I'm not a great Typescript expert
Hi everyone, I'm working on my personal site, I decided to develop it in Typescript to learn the language.
My component tree is composed, as usual, of App.tsx which render the sub-components, in this case Navbar.jsx and Home.jsx.
Below is the App.jsx code:
import './App.css';
import { BrowserRouter as Router, useRoutes } from 'react-router-dom';
import Home from './components/Home';
import Navbar from './components/Navbar';
import { useState } from 'react';
function App(){
const [navbarScroll,setNavbarScrool]=useState(Object)
const handleLocationChange = (navbarScroll : boolean) => {
setNavbarScrool(navbarScroll)
return navbarScroll
}
const AppRoutes = () => {
let routes = useRoutes([
{ path: "/", element: <Home handleLocationChange={handleLocationChange}/> },
{ path: "component2", element: <></> },
]);
return routes;
};
return (
<Router>
<Navbar navbarScroll={navbarScroll}/>
<AppRoutes/>
</Router>
);
}
export default App;
Here, instead, the Home.jsx code:
import { useInView } from 'react-intersection-observer';
import HomeCSS from "../styles/home.module.css"
import mePhoto from "../assets/me.png"
import { useEffect, useState } from 'react';
interface AppProps {
handleLocationChange: (values: any) => boolean;
}
export default function Home(props: AppProps){
const { ref: containerChange , inView: containerChangeIsVisible, entry} = useInView();
useEffect(()=>{
props.handleLocationChange(containerChangeIsVisible)
//returns false at first render as expected
console.log("Home "+containerChangeIsVisible)
},[])
return(
<>
<div className={`${ HomeCSS.container} ${containerChangeIsVisible? HomeCSS.container_variation: ''}`}>
<div className={HomeCSS.container__children}>
{/* when i scroll on the div the css change (this works)*/}
<h1 className={`${ HomeCSS.container__h1} ${containerChangeIsVisible? HomeCSS.container__h1_variation: ''}`}>My<br/> Name</h1>
<p>Computer Science student.</p>
</div>
<img src={mePhoto} className={HomeCSS.image_style}/>
</div>
<div ref={containerChange} style={{height:800,background:"orange"}}>
<p style={{marginTop:20}}>HIII</p>
</div>
</>
)
}
And Navbar.jsx:
import NavbarCSS from "../styles/navbar.module.css"
import acPhoto from "../assets/ac.png"
import { Link } from "react-router-dom";
import { useEffect, useState } from "react";
interface NavbarScroolProp{
navbarScroll:boolean
}
export default function Navbar(props:NavbarScroolProp){
const [scrollState,setScrollState]=useState(false)
const [pVisible,setpVisible] = useState('')
useEffect(()=>{
setTimeout(() => {
setpVisible("")
}, 3000)
setpVisible("100%")
},[])
//returns false also when should be true
console.log(props.navbarScroll)
return (
<>
{/*the props is undefined so the css doesn't change, i need to do this*/}
<nav className={`${props.navbarScroll?NavbarCSS.nav__variation:NavbarCSS.nav}`}>
<div className={NavbarCSS.nav_row}>
<div className={NavbarCSS.nav_row_container}>
<img src={acPhoto} className={NavbarCSS.image_style}/>
<p className={NavbarCSS.p_style} style={{maxWidth: pVisible}}>My name</p>
</div>
<div className={NavbarCSS.nav_row_tagcontainer}>
<Link className={NavbarCSS.nav_row_tag} to="/"> Home</Link>
<Link className={NavbarCSS.nav_row_tag} to="/"> About</Link>
<Link className={NavbarCSS.nav_row_tag} to="/"> Contact</Link>
</div>
</div>
</nav>
</>
);
}
In my application I want to change the background color whenever the div referring to the InsertionObserver ( I use "useInView" hook , from :https://github.com/thebuilder/react-intersection-observer) is displayed. The problem is that the div in question is in the Home.jsx component and I need to change the color of the divs in the navbar as well when the div in Home is triggered(or other components in case I need to in the future).
The question is: How can I dynamically trigger DOM elements of other components (to then perform certain operations) using the InsertionObserver ?
As you can see from the code I tried to create Props, but everything returns undefined and doesn't involve any changes.
I've tried without useEffect, without using the useInView hook, passing the object instead of the boolean value, but I can't find any solutions to this problem.
You would be of great help to me.
PS: I would like to leave the Navbar.jsx component where it is now, so that it is visible in all components.
Any advice or constructive criticism is welcome.

My Component isn't conditionally rendering properly

I have a simple react page so far where I just have a home component which seems to work fine it is made up from the code I have included what I am trying to do is to render another component the main component when the button that is part of the home component is clicked but it keeps giving me the error and I have no idea what I am doing wrong in this case I have included code for all of my files the main component isn't fully finished right now it was just to test what I am currently doing that I added a paragraph placeholder any help is appreciated thanks
Error: Unknown error
(/node_modules/react-dom/cjs/react-dom.development.js:3994) !The above
error occurred in the component: at Main (exe1.bundle.js:94:3)
at div at App (exe1.bundle.js:31:52) Consider adding an error boundary
to your tree to customize error handling behavior. Visit
https://reactjs.org/link/error-boundaries to learn more about error
boundaries. !Error: Unknown error
Home Component:
import React from "react";
export default function Home(props) {
return (
<main className="home-main">
<div className="content-container">
<div className="bottom-corner">
</div>
<div className="top-corner">
</div>
<h1 className="home-heading">Quizzical</h1>
<p className="home-description">Some description if needed</p>
<button
className="start-button"
onClick={props.handleClick}
>Start quiz
</button>
</div>
</main>
)
}
Main Component:
import react from "react";
export default function Main() {
return (
<h1>hello </h1>
)
}
App:
import React from "react";
import Main from "./components/Main"
import Home from "./components/Home"
export default function App() {
const [startQuiz, setStartQuiz] = React.useState(false);
function clickStart() {
// flip the state on each click of the button
console.log(startQuiz);
setStartQuiz(prevState => !prevState);
}
return (
<div>
{console.log("start", startQuiz)}
{startQuiz ?
<Main />
:
<Home handleClick={clickStart}/> }
}
</div>
)
}
Index:
import React from "react"
import ReactDOM from "react-dom"
import App from "./App";
ReactDOM.render(<App />, document.getElementById("root"))
I think you just have a typo here
import react from "react";
should be
import React from "react";
You can try changing your setStartQuiz to just simply negate the current startQuiz value instead of using prevState.
function clickStart() {
// flip the state on each click of the button
console.log(startQuiz);
setStartQuiz(!startQuiz);
}
Here's a working example based on your code.
code sandbox
import React, { useState } from "react";
const Main = () => <h1>hello </h1>;
const Home = (props) => {
return (
<main className="home-main">
<div className="content-container">
<div className="bottom-corner"></div>
<div className="top-corner"></div>
<h1 className="home-heading">Quizzical</h1>
<p className="home-description">Some description if needed</p>
<button className="start-button" onClick={props.handleClick}>
Start quiz
</button>
</div>
</main>
);
};
export default function App() {
const [startQuiz, setStartQuiz] = useState(false);
return (
<div>
{startQuiz && <Main />}
{!startQuiz && <Home handleClick={() => setStartQuiz(true)} />}
</div>
);
}

Route in React Js

I Have two components one is Main.js and Search.js I want to link button in Main.js to navigate to Search.js, but I'm not sure how to do it.
import React from "react";
import classes from "./Main.module.css";
import Aux from "../../hoc/Aux";
import logo from "../../containers/img/Logo.png";
import Search from "../Search/Search";
import { Route } from "react-router-dom";
const Main = () => {
return (
<Aux>
{/* Section starts */}
<section className={classes.Showcase}>
{/* Section Left */}
<div className={classes.ShowcaseLeft}>
<div className={classes.ShowcaseLeftTop}></div>
<div className={classes.ShowcaseLeftBottom}></div>
</div>
{/* Section Right */}
<div className={classes.ShowcaseRight}>
<div className={classes.ShowcaseRightTop}></div>
<div className={classes.ShowcaseRightRest}>
<img src={logo} alt="Logo" />
<p>
Provide weather, water, and climate data, forecasts and warnings
for the protection of life and property and enhancement of the
national economy.
</p>
<Route path="/auth" component={Search} />
</div>
</div>
</section>
</Aux>
);
};
export default Main;
You have two options: either use react-router-dom useHistory hook, or the Link component. Here are the two ways:
// useHistory
import { useHistory } from "react-router-dom";
function Main() {
let history = useHistory();
return (
<button type="button" onClick={()=> history.push("/search")}>
search
</button>
);
}
// Link
import { Link } from "react-router-dom";
function Main() {
let history = useHistory();
return (
<Link to="/search">
<button type="button">
search
</button>
</Link>
);
}
A last piece of advice: I would suggest to add all your paths in a single file, so you can never make any typo. In the end, the ideal would be to write something like: <Link to={path.search}>

How to direct to a new page when a button is clicked using ReactJS?

I am working in React.I have created a button ,which on click should lead the user to the newpage.I made a component About and imported it as well.
I created a function routeChange which would direct to a new page on Clicking the button.But when the button is clicked I am not being directed to any page .
Instead I get an error.
Probably there is not any error with folders.
I imported my About Component as:
import React from 'react';
import {Navbar,NavbarBrand, Jumbotron, Button} from 'reactstrap';
import './App.css';
import Description from './Description';
import './description.css';
import {useHistory,withRouter} from "react-router-dom";
import About from './About';
function App() {
const history=useHistory();
routeChange = () =>{
this.history.push('/About');
}
return (
<withRouter>
<Navbar color="dark">
<div className="container">
<NavbarBrand className="navbar-brand abs" href="/">
Cheat Sheet
</NavbarBrand>
</div>
</Navbar>
<Jumbotron>
<p className="lead">Quick Review ,Revision And Mnemonic Are Always Good</p>
<hr my-2/>
<p className="lead">Page is still under Construction</p>
<Button onClick={routeChange} className="About"color="primary">About Us</Button>
</Jumbotron>
<div className="img-thumbnail">
<Description/>
</div>
<div className="footer">
©Abhilekh Gautam all right reserved.
<p>Follow<a rel="noopener noreferrer"href="https://www.quora.com/profile/Abhilekh-Gautam-1" target="_blank">Abhilekh Gautam</a> On quora</p>
</div>
</withRouter>
)
}
export default App;
a couple issues here.
change function App (){} to const App = () => {} its going to help with your binding later because arrow functions are interpreted differently from declarative functions
this function needs some help
routeChange = () =>{
this.history.push('/About');
}
first of all you have to declare the function as a constant because App is a functional component not a class component.
second of all because App is a functional component you don't need the this keyword because routeChange is an arrow function and is bound to App
your final function should look like this:
const routeChange = () => {
history.push('/About');
}
make your button onClick handler an anonymous function so it is called on click only and not on render
<Button onClick={routeChange}/>
this code makes the route change function get called when the button renders. Instead change it to
<Button onClick={() => routeChange()}
make sure /About is a route to another component in your router or else you will get a 404 error or hit your no match component (if you have one)
your final product should look something like this
in app.js
import React from 'react';
import {Navbar,NavbarBrand, Jumbotron, Button} from 'reactstrap';
import './App.css';
import Description from './Description';
import './description.css';
import {useHistory,withRouter, BrowserRouter, Route, Switch} from "react-router-dom";
import About from './About';
function App() {
return (
<>
<Navbar color="dark">
<div className="container">
<NavbarBrand className="navbar-brand abs" href="/">
Cheat Sheet
</NavbarBrand>
</div>
</Navbar>
<BrowserRouter>
<Switch>
<Route exact path='/' component={Home}/>
<Route exact path='/About' component={About}
</Switch>
</BrowserRouter>
</>
)
}
then your home component would look like this:
import {useHistory} from 'react-router-dom'
const Home = () => {
const history = useHistory();
const routeChange = () => {
history.push('/About');
}
return (
<>
<Jumbotron>
<p className="lead">Quick Review ,Revision And Mnemonic Are Always Good</p>
<hr my-2/>
<p className="lead">Page is still under Construction</p>
<Button onClick={() => routeChange()} className="About"color="primary">About Us</Button>
</Jumbotron>
<div className="img-thumbnail">
<Description/>
</div>
<div className="footer">
©Abhilekh Gautam all right reserved.
<p>Follow<a rel="noopener noreferrer"href="https://www.quora.com/profile/Abhilekh-Gautam-1" target="_blank">Abhilekh Gautam</a> On quora</p>
</div>
</>
)
}
export default Home

Problem with the id of the items in shopping cart application in react

I am developing a shopping cart application . I am using redux and routing . There are mainly 3 pages Home,shop and About. I am adding authentication to the shop page and after successful authentication the user can enter into the shop page. In the shop page there are items which we can add to cart . totally i have 3 items in my shop page.whats my problem is when i am clicking add to cart for 1 st item it is displaying 3 items. I know the problem is with the id's of the items. But I am struggling from past one hour to resolve it.
Thanks in advance.
//App.js
import React ,{Component} from 'react';
import './App.css';
import Navigation from './Step1/Navbar'
import Home from './Step1/Home'
import Shop from './Step1/Shop'
import About from './Step1/About'
import Login from './LoginAuthentication/Loginform'
import {BrowserRouter as Router,Route} from 'react-router-dom'
import {connect} from 'react-redux'
const mapStateToProps=(state)=>{
return{
isLogin:state.isLogin
}
}
class App extends Component {
render(){
return (
<Router>
<div className="App">
<Navigation/>
<Route path="/" exact component={Home}/>
<Route path="/about" component={About}/>
<Route path="/shop"
render={() =>(
this.props.isLogin ? <Shop/> : <Login/>
) }
/>
</div>
</Router>
);
}
}
export default connect(mapStateToProps,null)(App);
//shop template.js
import React from 'react'
//import logo from '../cricket bat.jpg'
import Displaylist from '../Components/DisplayList'
const Shop_template=(props)=> {
return (
<div className="container">
<div className="row">
<div className="col-sm-6">
<div className="card-body">
<h4 className="card-title">{props.cardtitle}</h4>
<p className="card-text">{props.description}</p>
<h3>Price :{props.currency}{props.price}</h3>
<button type="button" onClick={props.cartHandler} className="btn btn-primary">Add to cart</button>
</div>
</div>
<div className="col-sm-6">
<Displaylist/>
</div>
</div>
</div>
)
}
export default Shop_template
//shop.js --> i am updating the state in shop.js to redux state
import React, { Component } from 'react'
import ShopTemplate from './Shop_template'
import {connect} from 'react-redux'
import {action2} from '../Actions/action1'
const mapDispatchToProps=(dispatch)=>({
CartHandler:(details)=>dispatch(action2(details))
})
class Shop extends Component {
state={
items:[
{id:1,cardtitle:'SSS Bat',description:'A stroke to score',currency:'$',price:100},
{id:2,cardtitle:'One upon a wall street',description:'A way to investment',currency:'$',price:50},
{id:3,cardtitle:'mi powerbank 10000mah',description:'Keep charged always',currency:'$',price:200}
]
}
cartHandler=()=>{
this.props.CartHandler(this.state.items)
}
render() {
const info=this.state.items.map((detail)=>{
return <ShopTemplate
cardtitle={detail.cardtitle}
description={detail.description}
currency={detail.currency}
price={detail.price}
key={detail.id}
cartHandler={this.cartHandler}
/>
})
return (
<div>
{info}
</div>
)
}
}
export default connect(null,mapDispatchToProps)(Shop)
/
/reducer.js
import {LOGINCHECK} from '../Constants/actiontypes'
import {ADDTOCART} from '../Constants/actiontypes'
const initialState={
isLogin:false,
items:[]
}
const reducer1=(state=initialState,action)=>{
//console.log(state)
if(action.type===LOGINCHECK){
return Object.assign({},state,{isLogin:true})
}
if(action.type===ADDTOCART){
return Object.assign({},state,{items:state.items.concat(action.payload)})
}
return state
}
export default reducer1
//DisplayList.js
import React from 'react'
import Display from './Display'
import {connect} from 'react-redux'
const mapStateToProps=(state)=>{
return{
items:state.items
}
}
const DisplayList=({items})=>{
console.log(items.body)
return(
<div>
{items.map(it=>{
return(
<Display iteminfo={it.body} key={it.body.id}/>
)
})
}
</div>
)
}
export default connect(mapStateToProps,null)(DisplayList)
//Display.js
import React from 'react'
const Display=({iteminfo:{id,cardtitle, description,currency,price}}) =>{
return (
<div>
<h4>{cardtitle}</h4>
<p>{description}</p>
<h3>{currency}{price}</h3>
<button type="button" className="btn btn-danger">Remove From cart</button>
</div>
)
}
export default Display
I can see too many problems in your source code,
first of all, namings can be better now it's confusing.
your shop items are in Shop component state but it has to be inside your redux module
initialState = {
items: ["your items should be here"]
}
of course, its because you are hardcoding your shop items. you may want to Get shop items from an API.
when you click on add to cart button you have to pass itemId to action. (right now you don't know which item is going to add to cart ).
and then inside reducer action.payload.itemId will be itemId that is added to cart then you can do something like this
const foundItem = state.items.find(it => it.id === action.payload.itemId);
now you found item in your products(items) array,
you can add this item to another array called basket or cart that represents items user added.
for the next step you want to add an inventory and quantity property to see how many items the user wants and how many do you have in your inventory
if you want a more detailed description don't hesitate to ask

Resources