I have build a mobile app which shows a list of movies. Its a static for now. I want to implement a react router for routing. What i want is when user clicks on the TV Shows from the list, he/she should be directed to the detail page of that TV Show. Not on the same page(layout) where list contains. I tried to do that but when i click on the title of the TV Show i am directed nowhere. How can i do that so?The code might help for expert to know what i am wanting and where i am doing wrong.
Here is my code first
Index.js
ReactDOM.render((
<Router history={browserHistory}>
<Route path="/" component={App} >
<Route component={DetailLayout}>
<Route name="flash" path="/flash" component={Flash} />
</Route>
</Route>
</Router>
), document.getElementById('root'));
MovieListItem.js(rendered by App.js)
const MovieListItem = ({movie}) => {
const imageUrl = movie.imageUrl;
const mainCastJoin = _.join(movie.mainCast, ', ');
return (<li className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl} alt={movie.title} />
</div>
<div className="media-body">
<div className="media-heading">
<Link to="flash"><h4 className="title">{movie.title}</h4></Link>
</div>
<div className="main-cast">
<ul id="cast-list">
<li className="list-item">
{mainCastJoin}...
</li>
</ul>
</div>
<div className="reviewer">
<img className="img-responsive reviewer-img" src={imdb} alt="{movie.title}" />
<div className="imdbScore">
{movie.imdb}
</div>
<img className="img-responsive reviewer-img" src={rottenTomatoes} alt="{movie.title}" />
<div style={{verticalAlign:'middle', display:'inline'}} className="rottenTomatoesScore">
{movie.rottenTomatoes}
</div>
</div>
</div>
</div>
</li>
)
};
export default MovieListItem;
Flash.js
import React, {Component} from 'react';
export default class Flash extends Component {
render() {
return (
<div>Detail page of Flash will be shown here with different Layout as in second image i have attached</div>
);
}
}
DetailLayout.js
export default class DetailLayout extends Component {
render() {
return (
<div>MyComponent</div>
);
}
}
When title of TV Show is clicked, i want to show its detail page which has completely different layout.
UPDATE
I dont know how but this works
ReactDOM.render((
<Router history={browserHistory}>
<Route path="/" component={App} >
</Route>
<Route path="detail" component={DetailLayout}>
<Route name="flash" path="/flash" component={Flash} />
</Route>
</Router>
), document.getElementById('root'));
In MovieListItem.js if i change to it works.
You are setting your flash route as a child of DetailLayout but it renders only MyComponent and has no children. Just include {this.props.children} in DetailLayout.
Set link in your MovieItemList as <Link to="/flash>
React router searches for all the routes and then renders the route it matches,and since we have added a /flash in the route it finds flash as child of / thats the reason it works.
You can also make it work by using detail/flash by handling the route inside flash as <Route name="flash" path="/detail/flash" component={Flash} />
export default class DetailLayout extends Component {
render() {
return (
<div>
<div>MyComponent</div>
<div>{this.props.children}</div>
</div>
);
}
}
Route
ReactDOM.render((
<Router history={browserHistory}>
<Route path="/" component={App} >
<Route name="detail" path="detail" component={DetailLayout}>
<Route name="flash" path="/flash" component={Flash} />
</Route>
</Route>
</Router>
), document.getElementById('root'));
MovieItem.js
const MovieListItem = ({movie}) => {
const imageUrl = movie.imageUrl;
const mainCastJoin = _.join(movie.mainCast, ', ');
return (<li className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl} alt={movie.title} />
</div>
<div className="media-body">
<div className="media-heading">
<Link to="flash"><h4 className="title">{movie.title}</h4></Link>
</div>
<div className="main-cast">
<ul id="cast-list">
<li className="list-item">
{mainCastJoin}...
</li>
</ul>
</div>
<div className="reviewer">
<img className="img-responsive reviewer-img" src={imdb} alt="{movie.title}" />
<div className="imdbScore">
{movie.imdb}
</div>
<img className="img-responsive reviewer-img" src={rottenTomatoes} alt="{movie.title}" />
<div style={{verticalAlign:'middle', display:'inline'}} className="rottenTomatoesScore">
{movie.rottenTomatoes}
</div>
</div>
</div>
</div>
</li>
)
};
export default MovieListItem;
Related
I am using react router dom to render a website with react and tailwindcss. The navbar when clicked refreshes and renders the component on it's own without the other components. This is not what I want.
I want the components rendered in a single page in the way it is structured in my App.js file
I have tried using normal hrefs and now Link from react-router-dom, But I still get the same result
App.js
const App = () => {
return (
<div className="max-w-[1440px] mx-auto bg-page overflow-hidden relative">
<Header />
<Routes>
<Route path="/" element={<Banner />} />
<Route path="/home" element={<Banner />} />
<Route path="/about" element={<About />} />
<Route path="/hero" element={<Hero />} />
<Route path="/featured" element={<Featured />} />
<Route path="/gallery" element={<GallerySection />} />
<Route path="/testimonies" element={<Testimony />} />
<Route path="/join" element={<Join />} />
<Route path="/footer" element={<Footer />} />
<Route path="/copy" element={<Copyright />} />
</Routes>
</div>
);
};
export default App;
Index.js
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Router>
<App />
</Router>
</React.StrictMode>
);
Navbar.js
const Nav = () => {
return (
<nav className="hidden lg:flex">
<ul className="flex gap-x-8 text-white">
{["home", "about", "featured", "gallery", "testimonies", "join"].map(
(item) => {
return (
<li key={`link-${item}`}>
<Link to={`/${item}`} className="capitalize">
{item}
</Link>
</li>
);
}
)}
</ul>
</nav>
);
};
export default Nav;
I would appreciate any help please
You need to use hashtags instead different routes.
So you have to use only one index route
<Route path="/" element={<IndexPage />} />
and render section components in IndexPage component one by one
const IndexPage = () => (
<>
<Banner />
...
</>
)
then add into each section component wrapper id attribute
const Banner = () => (
<div id="banner">
...content...
</div>
)
and use hashtag links in you Nav component:
<Link to={`#${item}`} className="capitalize">
{item}
</Link>
links will be looks like domain.com/#banner and if use open it then browser will scroll down to specific element with id
also I suggest to add some css to make scrolling smooth:
html {
scroll-behavior: smooth;
}
I installed react-router-dom to switch between navbar elements. The library does not want to cooperate with my project. After clicking on the navbar element I am not redirected to the required component. Sometimes when I click on a selected item the menu moves slightly to the left. My code looks like this:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
ReactDOM.render(
<App />, document.getElementById('root'));
Navbar.js
import React, { useState } from "react";
import App from '../components/App'
import About from '../components/About';
import Services from '../components/Services';
import Contact from '../components/Contact';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
const Navbar = () => {
const [navLinkOpen, navLinkToggle] = useState(false);
const handleNavLinksToggle = () => {
navLinkToggle(!navLinkOpen);
};
const renderClasses = () => {
let classes = "navlinks";
if(navLinkOpen) {
classes += " ' ' + active";
}
return classes;
};
return (
<nav>
<div className="logo">
<h4>Delightartco</h4>
</div>
<ul className={renderClasses()}>
<Router>
<li className="link"><Link to={"/home"}>Home</Link></li>
<li className="link"><Link to={"/about"}>About</Link></li>
<li className="link"><Link to={"/services"}>Services</Link></li>
<li className="link"><Link to={"/contact"}>Contact</Link></li>
<Switch>
<Route path="/home" component={App}>
</Route>
<Route path="/about" component={About}>
</Route>
<Route path="/services" component={Services}>
</Route>
<Route path="/contact" component={Contact}>
</Route>
</Switch>
</Router>
</ul>
<div onClick={handleNavLinksToggle} className="hamburger-toggle">
<i className="fas fa-bars fa-lg"></i>
</div>
</nav>
)
}
export default Navbar;
App.js
import React from 'react';
import '../../src/App.css';
import Navbar from './Navbar';
import Wrapper from './Wrapper';
import {Content, Winnie, Testimonials, Values, Secrets, Footer} from '../components/Content';
function App() {
return (
<div>
<Navbar />
<Wrapper />
<Content />
<Winnie />
<Testimonials />
<Values />
<Secrets />
<Footer />
</div>
)
}
export default App;
These are few issues in your code:
App is your root React component, and you gave it a route: <Route path="/home" component={App}></Route>. This is causing a recursive / infinite loop. App component inside App component.
Code structure looks complex.
Here is a proposed fixed code:
index.jsx:
ReactDOM.render(<App />, document.getElementById("root"));
App.jsx:
export default function App() {
return (
<StrictMode>
<Routes />
</StrictMode>
);
}
Routes.jsx:
export default function Routes() {
return (
<Router>
{/* Route components would be visible only at their route */}
<Switch>
<Route exact path="/about" component={About}></Route>
<Route exact path="/services" component={Services}></Route>
<Route exact path="/contact" component={Contact}></Route>
</Switch>
{/* Below components would be visible always at UI */}
<Navbar /> {/* Top navigation Link's */}
<Wrapper />
<Content />
<Winnie />
<Testimonials />
<Values />
<Secrets />
<Footer /> {/* Bottom navigation Link's */}
</Router>
);
}
There are several things to keep in mind when using react-router.
The Router or BrowserRouter component should wrap all your routes and your links. Generally, if your app does not need more than one Router, its better to wrap your whole App with the Router.
The Link component's job is to simply navigate to the page and can be used anywhere you want to show a link to someplace e.g. in the Navbar.
The Route (not Router) component's placement is very important. It should be placed where you want to render the content. In your code you are rendering the routes in the Navbar and are unable to see the routes being rendered due to invalid / improper structure.
Navbar.js
Your Navbar should only contain the links while the Router should be on the top-level and the Switch / Routes should be placed where you want to render the content.
function Navbar() {
return (
<nav>
{/* Move `Router` to top-level e.g. in App.js */}
<ul>
<li className="link">
<Link to={"/home"}>Home</Link>
</li>
<li className="link">
<Link to={"/about"}>About</Link>
</li>
<li className="link">
<Link to={"/services"}>Services</Link>
</li>
<li className="link">
<Link to={"/contact"}>Contact</Link>
</li>
</ul>
{/* Move `Switch and Routes` to where you want to render the content e.g. in Content.js */}
</nav>
);
}
App.js
function App() {
return (
<Router>
<div>
<Navbar />
<Wrapper />
<Switch>
<Route path="/home" component={App}></Route>
<Route path="/about" component={About}></Route>
<Route path="/services" component={Services}></Route>
<Route path="/contact" component={Contact}></Route>
</Switch>
<Winnie />
<Testimonials />
<Values />
<Secrets />
<Footer />
</div>
</Router>
);
}
I have a dynamic route set up like so:
import React, { Component } from 'react'
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom'
import DesktopHome from './DesktopHome'
import WhoWeAre from './WhoWeAre'
import WhatWeDo from './WhatWeDo'
import Articles from './Articles'
import Article from './Article'
import NotFound from './NotFound'
...
<Router>
<Switch>
<Route exact path='/' render={(props) => <DesktopHome {...props} api={this.state.api} acctok={this.state.acctok} />} />
<Route path='/who-we-are' render={(props) => <WhoWeAre {...props} api={this.state.api} acctok={this.state.acctok} />} />
<Route path='/what-we-do' render={(props) => <WhatWeDo {...props} api={this.state.api} acctok={this.state.acctok} />} />
<Route path='/articles/:id' component={(props) => <Article {...props} api={this.state.api} acctok={this.state.acctok} />} />
<Route path='/articles' render={(props) => <Articles {...props} api={this.state.api} acctok={this.state.acctok} />} />
<Route path='/not-found' component={NotFound} />
<Route component={NotFound} />
</Switch>
</Router>
The above code is for a navbar, when I go to 'articles/whatever' it works fine, however whenever that component renders if I try any of the links in the navbar I get 'articles/articles/whatever-component-route'
What I want to get is '/whatever-component-route'
edit
Added the component that displays the menu
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
class Menu extends Component {
render() {
return (
<div className='menu'>
<ul>
<Link to='./who-we-are'>
<li>
<div className='menuitem'>
<img src={require('./img/Menu Items-02.svg')} />
</div>
<h2>Who we are</h2>
</li>
</Link>
<Link to='./what-we-do'>
<li>
<div className='menuitem'>
<img src={require('./img/Menu Items-04.svg')} />
</div>
<h2>What we do</h2>
</li>
</Link>
<Link to='./articles'>
<li>
<div className='menuitem'>
<img src={require('./img/Menu Items-03.svg')} />
</div>
<h2>Articles</h2>
</li>
</Link>
<Link to='./past-projects'>
<li>
<div className='menuitem'>
<img src={require('./img/Menu Items-05.svg')} />
</div>
<h2>Past projects</h2>
</li>
</Link>
<Link to='./contact'>
<li>
<div className='menuitem'>
<img src={require('./img/Menu Items-01.svg')} />
</div>
<h2>Contact</h2>
</li>
</Link>
</ul>
</div>
)
}
}
export default Menu
Your problem is that you're using . before your routes. Remove the dot from all links and it will instead start at the root. Example:
to="/contact"
I have my app.js in that App.js I want to show some components when clicked on that router.
Here is my App.js code
import React from 'react';
import {BrowserRouter, Route} from 'react-router-dom';
import Header from './Header'
import Slider from './Slider';
import Section from './Section';
import Footer from './Footer';
import Register from './Register';
class IndecisionApp extends React.Component {
render() {
return (
<BrowserRouter>
<div className="wrapper">
<Header/>
<Route path="/register" component={Register}></Route>
<Slider />
<Section />
<Footer />
</div>
</BrowserRouter>
);
}
}
export default IndecisionApp;\
I want to hide Section and Slider components when I click on Router.
You are doing react-router wrong.
The correct way is this
<BrowserRouter>
<div className="wrapper">
<Header/>
<Switch>
<Route path="/register" component={Register}></Route>
</Switch>
<Slider />
<Section />
<Footer />
</div>
</BrowserRouter>
more on react router
https://reacttraining.com/react-router/web/guides/quick-start
Let say you have a home component and that only show as landing page including section and slide.
So there should be basically two route one is for landing another is for register, like follows
<Route path="/register" component={Register} />
<Route exact path="/" component={Home} />
But as your home/landing/index page should show section and slide together so I change the home route a little bit and finally it sum up with the following code
<BrowserRouter>
<div className="wrapper">
<Header />
<div>
<Link to="/">Home</Link>
<Link to="/register">Register</Link>
</div>
<Switch>
<Route path={"/register"} component={Register} />
<Route
exact
path="/"
render={() => (
<React.Fragment>
<Home />
<Slider />
<Section />
</React.Fragment>
)}
/>
</Switch>
<Footer />
</div>
</BrowserRouter>
Please make me clear if your idea is something different
I have this renderization done by reactJS
render() {
return (
<div>
<Router>
<div className="wrapper2">
<nav id="menu-principal" className="main menu-principal">
<ul>
<li><NavLink className="home-link" exact to="/">início</NavLink></li>
<li><NavLink exact to="/nota_biografica">nota biográfica</NavLink></li>
</ul>
</nav>
<div className="page-content">
<Route exact path='/nota_biografica' render={() => <NotaBiografica />} />
<Route exact path='/' render={() => <Home />} />
</div>
</div>
</Router>
</div>
)
}
When I click on the link that contains a "home-link" class, I would like to do some action. Like an action I tried to do in the example below which didn't work. How can I solve it? Thank you.
var el = document.querySelector(".menu-principal");
el.onclick = (event) => {
for(var i = 0; i < el.childNodes.length; i++) {
if(el.childNodes[i].className === "home-link"){
alert('true')
}
}
}
Because the element you targeted is <NavLink> tag which normally should navigate to another router page, I believe the event you have attached will not get running. I suggest you to not using <NavLink> just use this.props.history.push('/path/to/route') instead on the onClick handler ( after the procedures you need to run before navigating to another routing address ).
On the following example, Please pay attention about withRouter and i change <NavLink> to span then attach onHomeCLick handler to it:
import React, {Component} from 'react';
import {withRouter, Route, BrowserRouter as Router} from "react-router-dom";
class YourComponent extends Component {
onHomeCLick = () => {
//DO something here prior to router navigation of ".home-link" element
this.props.history.push( '/' );
};
render(){
return (
<div>
<Router>
<div className="wrapper2">
<nav id="menu-principal" className="main menu-principal">
<ul>
<li><span className="home-link" onClick={this.onHomeCLick}>início</span></li>
<li><NavLink exact to="/nota_biografica">nota biográfica</NavLink></li>
</ul>
</nav>
<div className="page-content">
<Route exact path='/nota_biografica' render={() => <NotaBiografica />} />
<Route exact path='/' render={() => <Home />} />
</div>
</div>
</Router>
</div>
)
}
}
export default withRouter( YourComponent );
UPDATE===========
Another trick if you like to use <NavLink>, the only solution is a "Call back" way. It will trigger once you navigated to the route ( I still can't see if there is way to do it prior to navigation ). Here we go:
import React, {Component} from 'react';
import {Route, BrowserRouter as Router} from "react-router-dom";
class YourComponent extends Component {
isActive= (match, location) => {
if (match) {
console.log('Hi i am active, do something here');
}
return match;
};
render(){
return (
<div>
<Router>
<div className="wrapper2">
<nav id="menu-principal" className="main menu-principal">
<ul>
<li><NavLink className="home-link" activeClassName="active" isActive={this.isActive}>início</NavLink></li>
<li><NavLink exact to="/nota_biografica">nota biográfica</NavLink></li>
</ul>
</nav>
<div className="page-content">
<Route exact path='/nota_biografica' render={() => <NotaBiografica />} />
<Route exact path='/' render={() => <Home />} />
</div>
</div>
</Router>
</div>
)
}
}
export default YourComponent;