React routing to endpoint but not rendering content - javascript

I can route to another endpoint, but the component content only appears on manual refresh.
I've seen this question asked here, here, and I've been checking out the reactrouter docs, amongst others. The solution always seems to be "add withRouter" or "make sure you're wrapping it in Router. I've done those things, but sadly got no where.
Here's the code:
App.js
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
function App() {
return (
<Router>
<Provider store={store}>
<div className="App">
<NavBar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/account" component={Account} />
</Switch>
</div>
</Provider>
</Router>
);
}
NavBar.js
import { BrowserRouter as Router, Link } from "react-router-dom";
import { withRouter } from "react-router";
function NavBar() {
return (
<Router>
<div className="navbar">
<h3>Connectory</h3>
<div className="buttons-container">
<Link>
<button>Settings</button>
</Link>
<Link to="/account"> // successfully redirects to /account, but doesn't render Account page content until refresh
<button>Account</button>
</Link>
</div>
</div>
</Router>
);
}
export default withRouter(NavBar);
EDIT: After comment suggestions, here's a code sandbox link and here;s the Account.js page:
import React from "react";
export default function Account() {
return (
<div>
<h3>This is the Account page</h3>
</div>
);
}

The Problem here is that, in your Navbar.js, you are re-setting your Routes again when they are already set in App.js.
<Switch>
<Route exact path="/" component={Home} />
<Route path="/account" component={Account} /> // Route for Applicatin set here
</Switch>
You do not need to do that again in. Check here.
https://codesandbox.io/s/gracious-germain-7fyry?file=/src/Navbar.js
Your Nabar should look like:
function NavBar() {
return (
<div className="navbar">
<h3>Connectory</h3>
<div className="buttons-container">
<Link to="/">
<button>Settings</button>
</Link>
<Link to="/account">
<button>Account</button>
</Link>
</div>
</div>
);
}

Hi i found a bug in your code and that's the reason because is not working.
in this component you are injecting the Router to the rest of the app.
function App() {
return (
<Router>
<div className="App">
<NavBar />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/account" component={Account} />
</Switch>
</div>
</Router>
);
}
in this one you are injecting again the Router. That's why is not working you just have to remove the Router from de Navbar and it will work properly.
function NavBar() {
return (
<Router>
<div className="navbar">
<h3>Connectory</h3>
<div className="buttons-container">
<Link>
<button>Settings</button>
</Link>
<Link to="/account">
<button>Account</button>
</Link>
</div>
</div>
</Router>
);
}
like this
function NavBar() {
return (
<div className="navbar">
<h3>Connectory</h3>
<div className="buttons-container">
<Link>
<button>Settings</button>
</Link>
<Link to="/account">
<button>Account</button>
</Link>
</div>
</div>
);
}

Related

Why does my react-router Link not take me to the other page (React JS)?

I have this code inside my App.js and i declared those routes:
function App() {
return (
<BrowserRouter>
<div className='App'>
<Switch>
<Route exact path="/"><Index /></Route>
<Route exact path="/contact"><Contact /></Route>
</Switch>
</div>
</BrowserRouter>
);
}
export default App;
And then in my Navbar.js i declared this link to /contact:
<Link to={ "/contact" } className="nav-item nav-link">Contact</Link>
And it doesn't work, the url changes into "http://localhost:3000/contact" but it remains in the index page, and the weird thing is that when i type exactly the same url in the url box it takes me to the contact page
Syntax error.
You wrote : Link to={ "/contact" } but it will be like : <Link to="/contact">Contact</Link>
I think It will be solved.
Your code wrong it shold be like that: to="/contact"
Well I would alter the code slightly:
import { BrowserRouter, Route, Routes } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div className='App'>
<Routes>
<Route index element={<Index />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
</BrowserRouter>
);
}
export default App;
The link code you have I've altered slightly too:
<Link to="/contact" className="nav-item nav-link">Contact</Link>
That's how we have ours and it is working fine, should be for you too.

React Routing V6 problem, redirecting to another path: '/contact' the content from <Contact /> get updated above nav instead of separate page

I am trying to make Airbnb Clone using React 18, but above nav something like this is happening:
I am using React BrowserRouter V6, whenever we redirect to another page like localhost:3000/about, the about page should open instead of the whole page rendering on all the paths:
App.js:
import './App.css';
import Title from './Components/Title.js'
import Tagline from './Components/Tagline.js'
import Navbar from './Components/Navbar.js'
import Firstpara from './Components/Firstpara.js'
import Card from './Components/Card.js'
import React, { Components } from 'react'
export default function App() {
return (
<div className="App">
<div className="header">
<Title />
<Tagline />
<Navbar />
</div>
<Firstpara />
<Card />
{/* <Contact/> */}
</div>
);
}
Navbar.js:
import React from 'react';
import { Link, BrowserRouter as Router, Route, Routes } from "react-router-dom";
import About from "../Pages/About"
import Contact from "../Pages/Contact"
import Features from "../Pages/Features"
import Error from '../Pages/Error'
export default function Navbar() {
return (
<>
<div className="navbar container-fluid">
<Router>
<Routes>
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/features" element={<Features />} />
<Route path="*" element={<Error />} />
</Routes>
<div id="right-menu">
<ul className="navbar-nav">
<li>Visit</li>
<li><Link to="/about">About</Link></li>
<li><Link to="/features">Features</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</div>
</Router>
</div>
</>
)
}
In your app.js file change your code to this (this is just for a demo) you change it as your requirements
import { BrowserRouter,Routes,Route,} from "react-router-dom";
import Navbar from "./components/navbar/Navbar";
import Register from "./components/auth/Register";
import Login from "./components/auth/Login";
return (
<>
<BrowserRouter>
<Navbar />
<Routes>
<Route path="/" index element={<Home />} />
<Route path="/login" element={<Login />}/>
<Route path="/register" element={<Login />}/>
<Routes/>
</BrowserRouter>
</>
);
I think the issue you have is that the Navbar is rendering all the routing code, the router, routes, and the links. Then additionally it is rendering the routes above the links.
Move the Router and routes out to the App. The Router should wrap the Navbar and routes, and the routes should be rendered below the Navbar/header.
Example:
App
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
export default function App() {
return (
<Router>
<div className="App">
<div className="header">
<Title />
<Tagline />
<Navbar />
</div>
<Routes>
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/features" element={<Features />} />
<Route path="*" element={<Error />} />
</Routes>
<Firstpara />
<Card />
{/* <Contact/> */}
</div>
</Router>
);
}
Navbar
import { Link } from "react-router-dom";
export default function Navbar() {
return (
<div className="navbar container-fluid">
<div id="right-menu">
<ul className="navbar-nav">
<li>Visit</li>
<li><Link to="/about">About</Link></li>
<li><Link to="/features">Features</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</div>
</div>
);
}

How do I make Portal be a single page all on it own

Sorry, extreme React newbie. I have a simple react function component:
import React from "react";
export default function Portal() {
return (
<h2>Portal</h2>
);
}
In my App.js I have:
import React from 'react';
import { BrowserRouter, Route, Switch } from "react-router-dom";
import './App.css';
import Portal from "./components/Portal/portal";
import LogoHeader from './components/LogoHeader';
import NewFooter from "./components/NewFooter";
function App() {
return (
<div className="App">
<BrowserRouter>
<Switch>
<Route path="/portal">
<Portal />
</Route>
</Switch>
</BrowserRouter>
...
<LogoHeader />
...
<NewFooter/>
</div>
);
}
export default App;
In LogoHeader I have a link:
<a href='/Portal'>Portal</a>
When I click the "Portal" link it refreshes the page, but it now displays the "Portal" header at the top and then the rest of the App.js page. How do I make Portal be a single page all on it own?
UPDATE
Based on an Answer given by #DrewReese I have changed App.js Render to:
return (
<div className="App">
<BrowserRouter>
<p className="greeting">Hello, {token.firstName}</p>
<LogoHeader />
<GetCategories />
<Navbar id="customNav" navItems={navItems} shopCategories={shopCategories} />
<Switch>
<Route path="/home">
<Slideshow id="slideshow" />
<div id="productContainer">
<br />
<h3>Featured Products</h3>
<br />
<FeaturedCards />
<br />
<h3>Most Popular</h3>
<br />
<ProdCard />
<br />
<h3>New Products</h3>
<br />
<ProdCard />
</div>
</Route>
<Route path="/portal">
<Portal />
</Route>
</Switch>
<NewFooter />
</BrowserRouter>
</div>
);
When you use an anchor tag (<a href="...." />) it will trigger a page reload, which reloads your React app. You should use the Link component to link to pages within your app.
LogoHeader
import { Link } from 'react-router-dom';
...
<Link to='/portal'>Portal</Link>
If you want the header to display rendered pages then move it up in the JSX. Remember, any links you render need to be rendered within a routing context, so the header should be rendered within the BrowserRouter component.
App
function App() {
return (
<div className="App">
<BrowserRouter>
<LogoHeader />
<Switch>
<Route path="/portal">
<Portal />
</Route>
</Switch>
<NewFooter/>
</BrowserRouter>
</div>
);
}
If you want the Portal page to be rendered and the header not to be rendered, then you can render a custom header and conditionally render LogoHeader based on route matching.
useRouteMatch
matchPath props
It returns null when provided pathname does not match path prop.
const Header = () => {
const match = useRouteMatch("/portal");
return !match ? <LogoHeader /> : null;
}
function App() {
return (
<div className="App">
<BrowserRouter>
<Header />
<Switch>
<Route path="/portal">
<Portal />
</Route>
</Switch>
<NewFooter/>
</BrowserRouter>
</div>
);
}
Update
Within the Switch component, path order and specificity matter. Order more specific paths before less specific paths. "/portal" is more specific than "/" so it should be rendered earlier. This is because the Switch component exclusively matches and renders routes (i.e. only the first match found), as opposed to the Router that inclusively renders them (i.e. all matches).
return (
<div className="App">
<BrowserRouter>
<p className="greeting">Hello, {token.firstName}</p>
<LogoHeader />
<GetCategories />
<Navbar id="customNav" navItems={navItems} shopCategories={shopCategories} />
<Switch>
<Route path="/portal">
<Portal />
</Route>
<Route path="/">
<Slideshow id="slideshow" />
<div id="productContainer">
<br />
<h3>Featured Products</h3>
<br />
<FeaturedCards />
<br />
<h3>Most Popular</h3>
<br />
<ProdCard />
<br />
<h3>New Products</h3>
<br />
<ProdCard />
</div>
</Route>
</Switch>
<NewFooter />
</BrowserRouter>
</div>
);
I suppose you just need to use <Link to="/portal"> from react-router here.
import { Link } from 'react-router-dom' (v4 of react-router)
import { Link } from 'react-router' (v3 of react-router)
There are 2 issues with using a tag:
it does contains relative urls (for this particular case it won't be a problem, but it confuse you on some pages).
it triggers page refresh
More info about using Link
https://reactrouter.com/web/guides/quick-start

Error is: A <Router> may have only one child element

I have problem in React.js when I save the code the website page say:
A <Router> may have only one child element
What is the problem and how can I solve it?
import React, { Component } from 'react';
import Head from './component/head';
import Contacts from './component/contacts';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import Addcontacts from './component/Addcontacts';
import { Provider } from "./context";
import 'bootstrap/dist/css/bootstrap.min.css';
class App extends Component {
render() {
return (
<Provider>
<Router>
<Head promo = 'alow' />
<div className='container'>
<Switch>
<Route exact path='/' Component={Contacts} />
<Route exact path='/add' Component={Addcontacts} />
</Switch>
</div>
</Router>
</Provider>
);
}
}
export default App;
you can use React.Fragment https://reactjs.org/docs/fragments.html#short-syntax to fix this issue.
<Router>
<>
<Head promo = 'alow' />
<div className='container'>
<Switch>
<Route exact path='/' Component={Contacts} />
<Route exact path='/add' Component={Addcontacts} />
</Switch>
</div>
</>
</Router>
So basically you just need to have a single tag in you compenent as a child.
Inside your <Router> wrap everything in a single <div> like this
<Router>
<div>
// all your content
</div>
</Router>
Router expect this.props.children to be null or to have length equal to 1
In your case its more than 1
So if you wrap all attr. inside a single tag it should work fine
You can use any of these
<> => React.Fragment
<div> => DIV
Eg:
class App extends Component {
render() {
return (
<Provider>
<Router>
<div>
<Head promo = 'alow' />
<div className='container'>
<Switch>
<Route exact path='/' Component={Contacts} />
<Route exact path='/add' Component={Addcontacts} />
</Switch>
</div>
</div>
</Router>
</Provider>
);
}
}

React-router v4 updates url but doesn't render component

I'm using react-router v4, no redux. The code example is below:
class MainPage extends Component {
render() {
return (
<div className="MainPage">
<BrowserRouter>
<Switch>
{/* <Route exact path='/' /> */}
<Route path='/signin' component={SignIn}/>
<Route path='/signup' component={SignUp} />
<Redirect from='*' to='/' />
</Switch>
</BrowserRouter>
</div>
);
}
}
When I'm using Link it updates URL in browser but doesn't render anything, nothing happens. When I resfresh, everything becomes fine and component renderes;
export default class Navbar extends Component {
render() {
return (
<div className="navbar">
<BrowserRouter>
<div>
<Link to='/signin'>Sign in</Link>
<Link to='/signup'>Sign up</Link>
</div>
</BrowserRouter>
</div>
);
}
}
I already tried everything, even withRouter(Component), but it says that with router may only be used inside
How can I deal with this?
Here is the working code. As others explained you should use one BrowserRouter. If you want to render your Navbar component all the time then you should place it above Switch but under BrowserRouter hence you need Link there.
const Navbar = () => (
<div className="navbar">
<Link to='/signin'>Sign in</Link>
<Link to='/signup'>Sign up</Link>
</div>
);
class MainPage extends React.Component {
render() {
return (
<div className="MainPage">
<BrowserRouter>
<div>
<Navbar />
<Switch>
{/* <Route exact path='/' /> */}
<Route path='/signin' component={SignIn} />
<Route path='/signup' component={SignUp} />
<Redirect from='*' to='/' />
</Switch>
</div>
</BrowserRouter>
</div>
);
}
}
You should only have a single BrowserRouter component in your tree. The BrowserRouter component holds the shared state the router used to synchronize the URL with the rendered routes. In your situation, you are getting two different versions of router state because you rendering two BrowserRouter components so you should probably render a single BrowserRouter component somewhere higher in your component tree.
If you have an App component that renders both Navbar and MainPage then you can move the router into that component:
export default class App extends Component {
render() {
return (
<BrowserRouter>
<div className="AppContainer">
<Navbar />
<MainPage />
</div>
</BrowserRouter>
);
}
}

Categories

Resources