After updated a bunch of our dependencies we are now are forced to use anchor tags which causes redirects, before we used but now everytime we click on a it goes to the proper url ie /screens but is just a blank page and never presents the components, below is our parent index.tsx file:
ReactDOM.render(
<Provider {...stores}>
{/* Changed routes to children */}
{/* <Router children={routes} history={createHistory} /> */}
<Router history={createHistory}>
<div>
<Switch>
<Route path='/oauth2callback' componentDidMount={console.log()}>
{() => {
if(window.location.href.includes('/oauth2callback'))
{
oauth2callback(window.location.hash)
}
}}
</Route>
<Route path='/testing' component={Get} />
<Route path='/'>
{/* Function that determines if the user is logged in and can allow the authenticated passage or not. If no, it will not render authenticated pages*/}
{() => {
if(auth.loggedIn())
{
console.log("is logged in")
return(
<div>
<Route component={App} history={createHistory}/>
<div className="row" id="wrapper">
<Switch>
{/* <Route path='/screens' component={Screens}/> */}
<Route path='/screens' component={Screens}/>
<Route path='/playlists' component={Playlists}/>
<Route path='/content' component={Content}/>
<Route path='/help' component={HelpNav}/>
<Route component={NotFound}/>
</Switch>
</div>
</div>
)
}
else
{
console.log("is not logged in")
return(
<Route path='/' component={HomeNav}/>
)
}
}}
</Route>
<Route path='401' component={Get} />
</Switch>
</div>
</Router>
</Provider>,
and here is the app.tsx with the navbar:
<Nav className="mb-nav">
{/* <IndexLinkContainer to="/screens"> */}
<Nav.Item style={{width: widthConstants[0]}}>
<Link to='/screens' style={{color: this.state.navIndex === 0 ? "white" : "bbddba"}}>
Screens
</Link>
</Nav.Item>
{/* </IndexLinkContainer> */}
{/* <LinkContainer to="/playlists"> */}
<Nav.Item style={{width: widthConstants[1]}}>
<a href="/playlists" style={{color: this.state.navIndex === 1 ? "white" : "bbddba"}}>
Playlists
</a>
</Nav.Item>
{/* </LinkContainer> */}
{/* <LinkContainer to="/content"> */}
<Nav.Item style={{width: widthConstants[2]}}>
<a href="/content" style={{color: this.state.navIndex === 2 ? "white" : "bbddba"}}>
Content
</a>
</Nav.Item>
{/* </LinkContainer> */}
{/* <LinkContainer to="/help"> */}
<Nav.Item style={{width: widthConstants[3]}}>
<a href="/help" style={{color: this.state.navIndex === 3 ? "white" : "bbddba"}}>
Help
</a>
</Nav.Item>
{/* </LinkContainer> */}
{this.shouldRenderTouch && <TouchButton/>}
</Nav>
</Navbar.Collapse>
</div>
</Navbar>
any idea what is different in the new react router update to cause this bug to exist?
The fix was much simpler than I thought, the new update integrated BrowserRouter instead of the Router so I replaced
<Router history={createHistory}>
with
<BrowserRouter>
and everything is now working as it should
Read "Routes and Links are relative to their parent" on this React Router 6 article
https://medium.com/frontend-digest/whats-new-in-react-router-6-732b06cc83e4
by the way it's strange that you have <a> tags instead of Link components sometimes
Related
I'm trying to change some "state varibale" managed component rendering into react-routing.I am using react-router 6.3.
This is the App.js
function App() {
return (
<Router>
<Header />
<Selections />
<Routes>
<Route path='/:type' element={<PostMain />}>
<Route path=':comments' index element={<Comments />} />
</Route>
</Routes>
</Router>
);
}
This is the Component
const handleLoadComments = () => {
if (!comments) {
dispatch(loadCommentsByPost(props.permalink));
} else {
navigate(-1);
//navigate(`/${type}`)
//console.log(type);
}
}
return (
<div className="Post">npm
<div className='Post-header' >
<p>Subbreddit: {props.subreddit_name_prefixed}</p>
<p>{created(props.created_utc)}</p>
</div>
<Media post={props} />
<div className='Post-footer-container' >
<div className='Post-footer' >
<div className='Post-footer-votes'>
<img src={upVote} alt="upvote" />
<p style={{color: "green"}} > {props.ups} -</p>
<img src={downVote} alt='downvote' />
<p style={{color: "red"}} > {props.downs}</p>
</div>
<Link to={`${props.id}`} >
<div className='Post-footer-comments' onClick={handleLoadComments} >
<input type="image" className='Comments-image' src={commentImg} alt='comment bubble' />
<p>{props.num_comments}</p>
</div>
</Link>
</div>
{/* { loading && <div className='Loading-container' ><img src={Loading} alt='loading' className='Comment-loading' /></div>} */}
</div>
<Outlet />
{/* {comments && <Comments comments={comments} />} */}
</div>
);
}
My goal would be to render the comments under the post, i did it with local state and setState before but is there a way to do it with routing?
I can see the change in the url when i click on a comment, i tried "navigate(/${type})" but not even the url changed so i used "navigate(-1)"
But the Comments component doesn't render!
Thanks in Advance!
Try to remove the path from the comments route since it's the index it sould be there by default
function App() {
return (
<Router>
<Header />
<Selections />
<Routes>
<Route path='/:type' element={<PostMain />}>
{/* <Route path=':comments' index element={<Comments />} /> */}
<Route index element={<Comments />} />
</Route>
</Routes>
</Router>
);
}
in your current approach you need to navigate to /type/comments, but it should be just /type
I am making a single page website. I added the Bootstrap navbar to Menu.js using React Router but once I add the menu.js to App.js the website becomes blank. Besides the links are not working. They are supposed to jump to the given component on the same page.
Here is my code for App.js
import "./App.css";
import "./components/Introduction";
import Menu from "./components/Menu";
import Introduction from "./components/Introduction";
import Team from "./components/Team";
import Products from "./components/Products";
import Contact from "./components/Contact";
import BackgroundImage from "./components/BackgroundImage";
import "bootstrap/dist/css/bootstrap.min.css";
function App() {
return (
<div className="App">
<Menu />
<BackgroundImage />
<div className="container titel text-center">
<h1>Titel</h1>
<h2>
<em>Subtitle</em>
</h2>
</div>
<Introduction />
<Products />
<Team />
<Contact />
</div>
);
}
export default App;
Here is my code for Menu.js (Navbar)
import React from "react";
import "./Menu.css";
import { Navbar, Nav, Container } from "react-bootstrap";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import Introduction from "./Introduction";
import Team from "./Team";
import Products from "./Products";
import Contact from "./Contact";
import App from "../App";
function Menu() {
return (
<Router>
<Navbar bg="light" expand="lg">
<Container>
<Navbar.Brand as={Link} to={"/"}>
React-Bootstrap
</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Nav.Link as={Link} to={"/introduction"}>
Introduction
</Nav.Link>
<Nav.Link as={Link} to={"/products"}>
Products
</Nav.Link>
<Nav.Link as={Link} to={"/team"}>
Team
</Nav.Link>
<Nav.Link as={Link} to={"/contact"}>
Contact
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
<Routes>
<Route exact path="/">
<App />
</Route>
<Route path="/introduction">
<Introduction />
</Route>
<Route path="/products">
<Products />
</Route>
<Route path="/team">
<Team />
</Route>
<Route path="/contact">
<Contact />
</Route>
</Routes>
</Router>
);
}
export default Menu;
I had to use Routes instead of Switch (error message).
I tried to add the code between Routes to index.js and also to App.js. But none of them worked.
You have put Menu inside of App, and App inside a route of Menu. Yes, this will go wrong (;
I recommend having a layout like this:
export const App = () => {
return (
<BrowserRouter>
// On every page, could be nav
<Router>
<Route></Route>
<Route></Route>
<Route></Route>
<Route></Route>
<Route></Route>
</Router>
// On every page
</BrowserRouter>
);
};
And not have the Router inside of your nav.
In react-router-dom#6 the Route component API changed. Routed components are rendered on a single element prop, not as children components of the Route. You might also want to wrap App with the Router component and render the routes there separately from the navigation component.
Example:
function App() {
return (
<Router>
<div className="App">
<Menu />
<BackgroundImage />
<div className="container titel text-center">
<h1>Titel</h1>
<h2>
<em>Subtitle</em>
</h2>
</div>
<Routes>
<Route path="/" element={<App />} />
<Route path="/introduction" element={<Introduction />} />
<Route path="/products" element={<Products />} />
<Route path="/team" element={<Team />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
</Router>
);
}
...
function Menu() {
return (
<Navbar bg="light" expand="lg">
<Container>
<Navbar.Brand as={Link} to="/">
React-Bootstrap
</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Nav.Link as={Link} to="/introduction">
Introduction
</Nav.Link>
<Nav.Link as={Link} to="/products">
Products
</Nav.Link>
<Nav.Link as={Link} to="/team">
Team
</Nav.Link>
<Nav.Link as={Link} to="/contact">
Contact
</Nav.Link>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
);
}
I have a problem with react-router. This is my /home component, the first page you see after logging in:
return(
<>
<CustomNavbar />
<Container fluid>
{ loading ? (
<div>Loading...</div>
) : (
<Router>
<ProtectedRoute
path='/home/mem'
render={(props) => <MResult
{...props}
data={data}
users={users} />
}
/>
<ProtectedRoute
path='/home/reading'
render={(props) => <RResult
{...props}
data={readingData}
users={users} />
}
/>
</Router>
)}
</Container>
</>
)
I have a table and I need to display different data based on the second part of the url (I'm using my own component ProtectedRoute to check for authentication, but the behaviour is the same we the usual Route component).
In the CustomNavbar component I have two links:
return(
<Navbar bg="primary" variant="dark">
<Navbar.Brand className='cursor-default'>
<span style={{marginLeft: "10px"}}></span>
</Navbar.Brand>
<Navbar.Toggle />
<Navbar.Collapse>
{ props.authenticated && (
<>
<Button>
<Link to="/home/reading">Reading</Link>
</Button>
<Button>
<Link to="/home/mem">MemResult</Link>
</Button>
</>
)}
</Navbar.Collapse>
<Navbar.Collapse className='justify-content-end'>
{ props.authenticated && (
<Button onClick={logout}>logout</Button>
)}
</Navbar.Collapse>
</Navbar>
)
The problem is that if I click on the links in the navbar I can see the url changing accordingly, but the new component is not being loaded, I still see the previous one. If I hit the browser's refresh button, then the correct component is loaded, but once that happened, again, clicking on the links won't change a thing but the url.
How can I fix this?
The CustomNavbar component is outside of the Router provider which is why Links aren't able to communicate to the Route component.
The solution is to render Router component at the top level and render CustomNavbar as a default route
return(
<Router>
<Route component={CustomNavbar} />
<Container fluid>
{ loading ? (
<div>Loading...</div>
) : (
<ProtectedRoute
path='/home/mem'
render={(props) => <MResult
{...props}
data={data}
users={users} />
}
/>
<ProtectedRoute
path='/home/reading'
render={(props) => <RResult
{...props}
data={readingData}
users={users} />
}
/>
</Router>
)}
</Container>
</Router>
)
Not really sure I'm doing wrong here. I have a header component which I am then using in my main app component where my "page" components are conditionally rendered based on the app. Manually going to the routes works, however React Router's Link component is not rendering the links as clickable buttons thus I can't click on anything...
Here is my header component:
function Header(props) {
const links = props.links.map(link => {
return (
<Link to={{pathname: link.path}} key={link.title}>{link.title}</Link>
);
});
return(
<Navbar className="border-bottom" bg="transparent" expand="lg">
<Navbar.Brand href="#home">Garrett Love</Navbar.Brand>
<Navbar.Toggle className="border-0" aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
{links}
</Nav>
</Navbar.Collapse>
</Navbar>
);
}
I did try setting the to prop as both to={link.path} and to="/about" but neither worked.
I'm just putting this component in my main app component like so:
render() {
return(
<Router>
<Container className="p-0" fluid={true}>
<Header links={this.state.headerLinks} />
<Route path="/" exact render={() => <Home title={this.state.home.title} subTitle={this.state.home.subTitle} />} />
<Route path="/about" render={() => <About title={this.state.about.title} />} />
<Footer />
</Container>
</Router>
);
}
I see you has header component and some app component
But in your app component you show <Gbar /> and dont show <Header />
The best way to fix this:
In Header
const Header = props =>
<Navbar className="border-bottom" bg="transparent" expand="lg">
<Navbar.Brand href="#home">Garrett Love</Navbar.Brand>
<Navbar.Toggle className="border-0" aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="ml-auto">
{props.links.map(link => <Link to={link.path} key={link.title}>{link.title}</Link>)}
</Nav>
</Navbar.Collapse>
</Navbar>
And in App:
render() {
return(
<Router>
<Container className="p-0" fluid={true}>
<Header links={this.state.headerLinks} />
<Route path="/" exact render={() => <Home title={this.state.home.title} subTitle={this.state.home.subTitle} />} />
<Route path="/about" render={() => <About title={this.state.about.title} />} />
<Footer />
</Container>
</Router>
);
}
I create simple app and i try use in it react-router but i have problem.
When user click register or login the page should render necessary form but now to page change user must refresh page and then page change component i dont know why.
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'))
App class:
class App extends React.Component {
render() {
return (
<div className="App">
<Navbar/>
</div>
);
}
}
Navbar class:
class Navbar extends React.Component {
render(){
return (
<Nav bsStyle="tabs">
<LinkContainer to="/login" >
<NavItem >
LogIn
</NavItem>
</LinkContainer>
<LinkContainer to="/Register" >
<NavItem >
Register
</NavItem>
</LinkContainer>
<Router>
<BrowserRouter>
<Switch>
<Route path="/Register" component={Register} />
<Route path="/Login" component={Login} />
</Switch>
</BrowserRouter>
</Router>
</Nav>
)
}}
You will have to have your BrowserRouter as a top level component. The nav is the place which triggers what component has to be rendered.
ReactDOM.render(<App />, document.getElementById('root'));
App.js
class App extends React.Component {
render() {
return (
<div className="App">
<Navbar/>
<Router>
<BrowserRouter>
<Switch>
<Route path="/Register" component={Register} />
<Route path="/Login" component={Login} />
</Switch>
</BrowserRouter>
</Router>
</div>
);
}
}
Nav.js
class Navbar extends React.Component {
render(){
return (
<Nav bsStyle="tabs">
<LinkContainer to="/login" >
<NavItem >
LogIn
</NavItem>
</LinkContainer>
<LinkContainer to="/Register" >
<NavItem >
Register
</NavItem>
</LinkContainer>
</Nav>
)
}}
You have your Routing inside the Navbar component, that won't work.
Change your index.js to look like this:
ReactDOM.render((
<BrowserRouter>
<Switch>
<Route path="/Register" component={Register} />
<Route path="/Login" component={Login} />
<Route path="/" component={App} />
</Switch>
</BrowserRouter>
), document.getElementById('root'))
That should work, let me know if any issues. Also delete the BrowserRouter elements and children from Navbar
use BrowserRouter inside Router
<Router>
<BrowserRouter>
<Switch>
...
</Switch>
</BrowserRouter>
</Router>