Routes working fine but not rendering components - javascript

I am routing between child components in a parent component. Routes are working fine on click but the child components are not rendering on page. No errors in console. No errors in code according to ChatGPT.
I resolved every issue but components do not render on page even route is working fine in url and there are no errors in console.
App.js
import './App.css';
import Navbar from './components/Navbar';
import { Routes, Route } from 'react-router-dom';
import NewOrder from './components/NewOrder';
import Orders from './components/Orders';
function App() {
return (
<>
<Navbar />
<Routes>
<Route path='/newOrder/*' element={<NewOrder />} />
<Route exact path='/orders' element={<Orders />} />
</Routes>
</>
);
}
export default App;
NewOrder.jsx
import React from 'react'
import { Link, Route, Routes } from 'react-router-dom'
import ChooseBun from './ChooseBun.jsx'
import ChooseFillet from './ChooseFillet.jsx'
import './NewOrder.css'
const NewOrder = () => {
return (
<>
<div className='container'>
<h1>Make Your Own Burger!</h1>
<ul>
<li>
<Link to="/newOrder/choose-bun">Child 1</Link>
</li>
<li>
<Link to="/newOrder/choose-meat">Child 2</Link>
</li>
</ul>
{/* <ChooseBun/> */}
<Routes>
<Route path='/newOrder/choose-bun' element={<ChooseBun />} />
<Route path='/newOrder/choose-meat' element={<ChooseFillet />} />
</Routes>
</div>
</>
)
}
export default NewOrder
Child1 which is ChooseBun.jsx
import React, { useEffect, useRef, useState } from 'react'
import './NewOrder.css'
import bun1 from '../images/front-view-tasty-meat-burger-with-cheese-salad-dark-background.jpg'
import { useNavigate } from 'react-router-dom'
const ChooseBun = () => {
const ref = useRef(null);
const [selectImage, setSelectImage] = useState('');
const [select, setSelect] = useState(false);
const handleImageClick = (id) => {
setSelectImage(id);
setSelect(true);
};
useEffect(() => {
const handleClickOutside = (e) => {
if (ref.current && !ref.current.contains(e.target)) {
setSelectImage('');
setSelect(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
let navigate = useNavigate();
return (
<>
<div className="choose-bun">
<h2>Choose Your Bun</h2>
<div ref={ref}>
<div className='mainContainer mt-5'>
<img
src={bun1}
alt="Brioche Bun"
className={`col-3 ${selectImage === 'img1' ? 'selected' : ''}`}
onClick={() => handleImageClick('img1')}
/>
<img
src={bun1}
alt="Brioche Bun"
className={`col-3 ${selectImage === 'img2' ? 'selected' : ''}`}
onClick={() => handleImageClick('img2')}
/>
<img
src={bun1}
alt="Brioche Bun"
className={`col-3 ${selectImage === 'img3' ? 'selected' : ''}`}
onClick={() => handleImageClick('img3')}
/>
</div>
<div className='mainContainer mt-5'>
<img
src={bun1}
alt="Brioche Bun"
className={`col-3 ${selectImage === 'img4' ? 'selected' : ''}`}
onClick={() => handleImageClick('img4')}
/>
<img
src={bun1}
alt="Brioche Bun"
className={`col-3 ${selectImage === 'img5' ? 'selected' : ''}`}
onClick={() => handleImageClick('img5')}
/>
<img
src={bun1}
alt="Brioche Bun"
className={`col-3 ${selectImage === 'img6' ? 'selected' : ''}`}
onClick={() => handleImageClick('img6')}
/>
</div>
</div>
<button
className='btn btn-danger'
disabled={!select}
onClick={() => navigate('/newOrder/choose-meat')}
>
Next
</button>
</div>
</>
);
};
export default ChooseBun

I Edit your App.jsx to : wrap your Routes with BrowserRouter :
function App() {
return (
<>
<BrowserRouter>
<Navbar />
<Routes>
<Route path='/newOrder' element={<NewOrder />} >
<Route path='choose-bun' element={<ChooseBun />} />
<Route path='choose-meat' element={<ChooseFillet />} />
</Route>
<Route exact path='/orders' element={<Orders />} />
</Routes>
</BrowserRouter>
</>
);
}
export default App;
ChoosenFillet And ChooseBun are child of NewOrder. for access them in NewOrder, use Outlet
NewOrder.jsx :
import { Outlet } from 'react-router-dom';
const NewOrder = () => {
return (
<>
<div className='container'>
<h1>Make Your Own Burger!</h1>
<ul>
<li>
<Link to="/newOrder/choose-bun">Child 1</Link>
</li>
<li>
<Link to="/newOrder/choose-meat">Child 2</Link>
</li>
</ul>
{/* <ChooseBun/> */}
<Outlet />
</div>
</>
)
}

Descendent routes in a Routes component build their paths relative to the parent route. The issue is that in the NewOrder component the routes will be relative from the parent "/newOrder/*" route path. In other words, the paths are actually "/newOrder/newOrder/choose-bun" and "/newOrder/newOrder/choose-meat".
You should omit the leading "/newOrder" prefix from the descendent routes.
const NewOrder = () => {
return (
<>
<div className="container">
<h1>Make Your Own Burger!</h1>
<ul>
<li>
<Link to="/newOrder/choose-bun">Child 1</Link>
</li>
<li>
<Link to="/newOrder/choose-meat">Child 2</Link>
</li>
</ul>
{/* <ChooseBun/> */}
<Routes>
<Route path="/choose-bun" element={<ChooseBun />} />
<Route path="/choose-meat" element={<ChooseFillet />} />
</Routes>
</div>
</>
);
};

Related

How to pass an array object from a component to a page in reactjs

Child
import React from "react";
import { Link } from "react-router-dom";
import "../pages/All.css";
const MovieList = (props) => {
return(
<>
{props.movies.map((movie, index) => (
<div className="ro">
<img src={movie.Poster} alt={movie.Title} /> <br /> <br />
<label>{movie.Title}</label> <br />
<p>{movie.Type} {movie.Year}</p> <br /> <br />
<div className="overlay">
<li><Link to = "/play" class="popup-video btn">Watch</Link></li>
<li><Link to ="movie-details.html" class="btn">Download</Link></li>
</div>
</div>
))}
</>
);
};
export default MovieList;
import React from "react";
import ReactPlayer from "react-player";
function Play(movie){
return(
<div>
<ReactPlayer width="100%" height="750px" controls url ={"http://www.youtube.com/"+movie.Title} />
</div>
);
}
export default Play;
i am trying to pass {movie.Title} to controls url in Parent Component
I hope what you want to ask is how to pass params.
const MainNavigation = ()=> (
<Routes>
<Route path="/" element={<VideoList />} />
<Route path="/play:id" element={<Play />} />
</Routes>
)
const VideoList = ()=> (
<Link to={"/play/" + movie.title}>{movie.title}</Link>
)
const Play = ()=> {
const {id} = useParams();
return (
<VideoComponent url={"https://example.com/" + id} />
)
}
For more information, read official documents. https://reactrouter.com/docs/en/v6/hooks/use-params

React Router Navigate Issue in Semantic Ui React

I have an issue with navigating pages via Route.
I used semantic ui react components to handle with the issue.
When I link any item in navbar, the url is changed like http://localhost:3000/ to http://localhost:3000/list but the relevant component page cannot open.
How can I fix it?
Here is my index.js code shown below.
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter> ,
document.getElementById('root')
);
Here is my App.js code shown below.
function App() {
return (
<div className="App">
<Container style={{"marginTop": "20px"}}>
<Header />
<Route path="/">
<AccordionComponent items={items} />
</Route>
<Route path="/list">
<Search />
</Route>
<Route path="/dropdown">
<DropdownForm options={options}/>;
</Route>
<Route path="/translate">
<Translate />
</Route>
</Container>
</div>
);
}
export default App;
Here is my Route Component shown below.
const Route = ({ path, children }) => {
return window.location.pathname === path ? children : null;
};
export default Route;
Here is my Header Component shown below.
import React, { useState } from 'react';
import { Menu } from 'semantic-ui-react'
import { Link } from "react-router-dom";
const Header = () => {
const [activeItem, setActiveItem] = useState('Accordion');
const handleItemClick = (name) => setActiveItem(name)
return (
<Menu secondary pointing>
<Menu.Item
as={Link} to="/"
name='Accordion'
active={activeItem === 'Accordion'}
onClick={() => handleItemClick('Accordion')}
/>
<Menu.Item
as={Link} to="/list"
name='Search'
active={activeItem === 'Search'}
onClick={() => handleItemClick('Search')}
/>
<Menu.Item
as={Link} to="/dropdown"
name='Dropdown'
active={activeItem === 'Dropdown'}
onClick={() => handleItemClick('Dropdown')}
/>
<Menu.Item
as={Link} to="/translate"
name='Translate'
active={activeItem === 'Translate'}
onClick={() => handleItemClick('Translate')}
/>
</Menu>
);
};
export default Header;
Wrap de routes with Switch as this example:
function App() {
return (
<div className="App">
<Container style={{"marginTop": "20px"}}>
<Header />
<Switch>
<Route path="/">
<AccordionComponent items={items} />
</Route>
<Route path="/list">
<Search />
</Route>
<Route path="/dropdown">
<DropdownForm options={options}/>;
</Route>
<Route path="/translate">
<Translate />
</Route>
</Switch>
</Container>
</div>
);
}
export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Docs: https://reactrouter.com/web/api/Switch

I want to pass an image as a prop to another page

The main problem is that this image is selected from the file explorer and I am using react-router.
Add.js
this is where you select the image
import { Link } from "react-router-dom";
import About from "./About";
import './styles/modal.css'
import firebase from "firebase";
require("firebase/firestore")
require("firebase/storage")
export default function Add(props) {
const [image, setImage] = useState(null);
const [modal, setModal] = useState(false);
const pickImage = (event) => {
//console.log();
setImage(URL.createObjectURL(event.target.files[0]));
//console.log(image);
}
const toggle = () => {
setModal(!modal);
}
return (
<div>
<h1>Add</h1>
<button onClick={toggle}>Add image</button>
{modal ? (
<div className="modal-bg">
<div className="modal">
<img src={image} style={{ width: '60%', height: '60%' }} className="ex-img" />
<br /><br />
<label htmlFor="fie" className="gcoo btn-default">+ File
<input id="fie" type="file" onChange={pickImage} className="file-pick" />
</label>
<br />
<br />
<div className="bottom-buttons">
<Link to="/about">
<button className="save">Save</button>
</Link>
<button onClick={() => setModal(false)} className="closse">Close</button>
</div>
</div>
</div>
) : null}
</div>
)
}
I am using firebase but not in this file so you can ignore this.
MainRoutes.js
this is where all the routes and pages are.
import { Route } from "react-router";
import { Switch } from 'react-router-dom';
import ImageDisplay from "./components/ImageDisplay";
import Add from './components/Add';
export default function MainRoute(props) {
return (
<Switch>
<Route exact path="/about" component={() => <ImageDisplay />} />
<Route exact path="/add" component={() => <Add />} />
</Switch>
);
}
finally this file ImageDisplay.js is where the image should be displayed
I dont have much on this file because i dont know how to put in any images.
I have tried props but whenever i imported the Imagedisplay it always showed the content on it and i dont want anything from image display. I only want to send an image over there.
import React from 'react'
import { Link } from "react-router-dom"
function ImageDisplay(props) {
return (
<div>
<h1>image</h1>
<div>
<img />
<p></p>
</div>
</div>
)
}
export default ImageDisplay;
Make sure that you are not reloading the page when moving between the two routes, since this will remove all state.
To share state between the two components you would need to store the state in the parent, and pass it to the children.
Add:
export default function Add(props) {
const pickImage = (event) => {
props.setImage(URL.createObjectURL(event.target.files[0]));
}
// The rest of your function
}
And in your parent:
export default function MainRoute(props) {
const [image, setImage] = useState(null)
return (
<Switch>
<Route exact path="/about" component={() => <ImageDisplay image={image} />} />
<Route exact path="/add" component={() => <Add setImage={setImage} />} />
</Switch>
);
}
You can now access the image prop in your imageDisplay.
function ImageDisplay(props) {
return (
<div>
<h1>image</h1>
<div>
<img src={props.image} />
<p></p>
</div>
</div>
)
}

Display Component on click over another Component ReactJS

I have Menu component. I'm adding items to Cart component by clicking on Add to Cart button.
I also have a Cart icon which holds array of items in Cart.
const Menu = () => {
const [cart, setCart] = useState([]);
const addToCart = (el) => setCart( [...cart, el]);
console.log(cart);
return (
<>
<Tabs className="tabs-wrapper" id="menu">
<TabList className="tabs">
<Tab className="tab-item">Burgers</Tab>
<Tab className="tab-item">Lunch of the day</Tab>
<Tab className="tab-item">Crepes</Tab>
</TabList>
<TabPanel>
<div className="burgers">
<ul>
{burgers.map(burger => (
<li key={burger.id}>
<h4>{burger.title}</h4>
<span>{burger.price}</span>
<img src={burger.image} alt={burger.title} />
<p>{burger.description}</p>
<button type="submit" onClick={() => addToCart(burger, "burger")}>Add to cart</button>
</li>
))}
</ul>
</div>
</TabPanel>
<TabPanel>
<div className="lunch">
<h4>Sweet lunch today!</h4>
<span>7$</span>
<p>You can choose one of our 3 sweet crepes + one of our 4 cold drinks!
<br />
Nutella crepe, Crepe with salted caramel and nuts or Oreo Bang crepe with whipped cream and raspberries.
<br />
For drink - one of our homemade lemonades - Melon, Orange or Lemon-Mint. Or a Frozen Coffee!
</p>
<div>
<img src={sweetLunch} alt="Sweet crepe lunch" />
<img src={sweetCrepes} alt="Sweet crepes lunch" />
</div>
</div>
</TabPanel>
<TabPanel>
<div className="crepes">
<ul>
{crepes.map(crepe => (
<li key={crepe.id}>
<h4>{crepe.title}</h4>
<span>{crepe.price}</span>
<img src={crepe.image} alt={crepe.title} />
<p>{crepe.description}</p>
<button type="submit" onClick={() => addToCart(crepe, "crepe")}>Add to cart</button>
</li>
))}
</ul>
</div>
</TabPanel>
</Tabs>
<FontAwesomeIcon className="cart" icon={["fas", "shopping-cart"]} onClick={() => setCart(cart)}/>
</>
)
}
I want to make Cart component appear above Menu component, display on the right side and take a half of screen(like on Upwork when you click on jod in feed) when I click on Cart icon.
So I tried to import Cart component (which also holds a Form) into Menu component
const Cart = ({ cart }) => {
const { image, title, price } = cart;
return (
<>
<li>
<img src={image} alt={title} />
<h4>{title}</h4>
<span>{price}</span>
</li>
<Form />
</>
)
}
and got
TypeError: Cannot destructure property 'image' of 'cart' as it is undefined.
at Cart (Cart.jsx:6)
My App.jsx looks like this
import React, { useState } from "react";
import {
BrowserRouter as Router,
Route,
Switch,
Redirect
} from "react-router-dom";
import './App.css';
import './Responsive.css';
const Header = React.lazy(() => import("./components/Header"));
const Footer = React.lazy(() => import("./components/Footer"));
const Home = React.lazy(() => import("./components/Home"));
const Menu = React.lazy(() => import("./components/Menu"));
function App() {
const [cart, setCart] = useState([]);
return (
<Router>
<React.Suspense fallback={<p className="loader">Loading...</p>}>
<Header />
<Switch>
<Route path="/home" render={props => <Home {...props} />} />
<Route path="/menu" render={props => <Menu cart={cart} {...props} />} />
<Route exact path="/">
<Redirect to="/home" />
</Route>
</Switch>
<Footer/>
</React.Suspense>
</Router>
);
}
export default App;
props which you try to pass is an empty table
const [cart, setCart] = useState([]);
<Menu cart={cart} />
After some restructuring I managed to find an answer for displaying cart items
{cart.map((el) => (
<Cart
key={el.id}
product={el}
removeFromCart={removeFromCart}
/>
))}
And Cart component itself
export default function Cart ({ product, removeFromCart }) {
const { image, title, price } = product;

Reactjs - props not changing during Routing

I have a BrowserRouter which renders different components based on the Route. Most, of these components have similar markup.
So, I created a Wrapper component which will recieve props, and render its {children} if provided. This Wrapper is called in Route's.
import React, {Component} from 'react'
import Context from '../../provider'
import {
BrowserRouter,
Route,
Redirect,
Switch,
} from "react-router-dom"
import {
Container,
Row,
Col,
} from 'reactstrap'
import Profile from './ContentComponent/Profile'
import Subreddit from './ContentComponent/Subreddit'
import PostExpanded from './ContentComponent/PostExpanded'
import InfoComponent from './InfoComponent'
import SwitchTab from './ContentComponent/Subreddit/SwitchTab'
import NewPost from './ContentComponent/assets/NewPost'
import './style.css'
class Wrapper extends React.Component {
componentDidMount() {
this.props.setActiveTab(this.props.activeTab);
}
render() {
{console.log('Wrapper props: ', this.props)}
return (
<Row>
<Col md='8' id='content-block'>
<SwitchTab />
{this.props.children}
</Col>
<Col md='4' id='info-block'>
<InfoComponent info={this.props.info} {...this.props}/>
</Col>
</Row>
)
}
}
export default class BodyComponent extends Component {
render() {
return (
<BrowserRouter>
<Context.Consumer>
{context => {
return (
<Container>
<Switch>
<Route
exact
path='/'
render={() =>
<Redirect to='r/home/' />
}
/>
<Route
exact
path='/r/home/'
render={() =>
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'1'}
info='home'
/>
}
/>
<Route
exact
path='/r/popular/'
render={() =>
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'2'}
info='popular'
/>
}
/>
<Route
exact
path='/r/all/'
render={() =>
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'3'}
info='all'
/>
}
/>
<Route
exact
path='/u/:username/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='user'
user={props.match.params.username}
>
<Profile username={props.match.params.username} />
</Wrapper>
)
}}
/>
<Route
exact
path = '/r/:subreddit/new/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='subreddit'
subreddit={props.match.params.subreddit}
>
<NewPost />
</Wrapper>
)
}}
/>
<Route
exact
path = '/r/:subreddit/post/:postid/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='subreddit'
subreddit={props.match.params.subreddit}
>
<PostExpanded
subreddit={props.match.params.subreddit}
postid={props.match.params.postid}
/>
</Wrapper>
)
}}
/>
<Route
exact
path='/r/:subreddit/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='subreddit'
subreddit={props.match.params.subreddit}
>
<Subreddit subreddit={props.match.params.subreddit} />
</Wrapper>
)
}}
/>
<Route
exact
path = '/new/'
render={(props) => {
return (
<Wrapper
setActiveTab={context.toggleTab}
activeTab={'4'}
info='new'
>
<NewPost />
</Wrapper>
)
}}
/>
</Switch>
</Container>
)
}}
</Context.Consumer>
</BrowserRouter>
)
}
}
I am facing multiple problems here and I think they can all be fixed at once, I don't know how?
The Wrapper props are not getting changed when I am changing the URL
using props.history.push:
<NavItem>
<NavLink
className={classnames({ active: context.activeTab === '1' })}
onClick={() =>{
context.toggleTab('1');
this.props.history.push('/r/home/')
}}
>
Home
</NavLink>
</NavItem>
<NavItem>
<NavLink
className={classnames({ active: context.activeTab === '2' })}
onClick={() => {
context.toggleTab('2');
this.props.history.push('/r/popular/')
}}
>
Popular
</NavLink>
</NavItem>
I think I got the problem while going through my code. So, the problem started when I wanted to use props.history.push in my HeaderComponent. I was getting error so I wrapped it with BrowserRouter and exported withRouter() which enabled me to use props.history.push
So, unknowingly I have created 2 BrowserRouter's:
<React.Fragment>
<BrowserRouter>
<NavbarComponent />
<TabComponent />
</BrowserRouter>
<BrowserRouter>
<Switch>
<Route ... />
<Route ... />
</Switch>
</BroserRouter>
</React.Fragment>
So, I was changing URLs in TabComponent and expecting that to change my Route's and modify content.
Having a global BrowserRouter (don't think that global's the right word but) solved the problem.
<React.Fragment>
<BrowserRouter>
<NavbarComponent />
<TabComponent />
<Switch>
<Route ... />
<Route ... />
</Switch>
</BroserRouter>
</React.Fragment>

Categories