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

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>
);
}
}

Related

React Router - Why is the switch not changing html when the path changes?

I am working on a web app, and i am having some issues with reactJS Router. When i redirect to the /sell path the HTML form the / path stays, and the HTML inside the /sell route doesn't load.
Am i doing something wrong? would anyone be able to point me towards the right direction?
import React, { Component } from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import Helmet from "react-helmet";
import CreateList from "./CreateList";
//https://colorhunt.co/palette/33990
//https://colorhunt.co/palette/66990
class Home extends Component {
constructor(props) {
super(props);
this.state = { appTitle: "better craigslist"};
}
render() {
return (
<React.Fragment>
<Helmet>
<title>{this.state.appTitle}</title>
</Helmet>
<Router>
<Switch>
<Route path="/">
<div id="header-text">
<h1 className="center-align">
<b>Sellify</b>
</h1>
<h5 className="center-align">
Need to get rid of your stuff? create a listing and sell it here! <br /> Looking for something? Check if its on selify!
</h5>
</div>
<div className="col s12 center">
<Router>
<Link to="/sell">
<button className="btn" id="create-listing-button">
Create Listing
</button>
</Link>
</Router>
</div>
</Route>
<Route path="/sell">
<h1>Test</h1>
</Route>
</Switch>
</Router>
</React.Fragment>
);
}
}
export default Home;
Thank you very much!
Issue
You've more than one Router. The inner Router context is handling the links so the outer Router isn't notified.
Solution
Use only one Router component, remove the Router around the Link. Additionally, when using a Switch, path order and specificity matter. You want to oder your more specific paths before less specific paths. "/" is a path prefix for all paths and would be matched and rendered before "/sell".
class Home extends Component {
constructor(props) {
super(props);
this.state = { appTitle: "better craigslist" };
}
render() {
return (
<React.Fragment>
<Helmet>
<title>{this.state.appTitle}</title>
</Helmet>
<Router>
<Switch>
<Route path="/sell">
<h1>Test</h1>
</Route>
<Route path="/">
...
<div className="col s12 center">
<Link to="/sell">
<button className="btn" id="create-listing-button">
Create Listing
</button>
</Link>
</div>
</Route>
</Switch>
</Router>
</React.Fragment>
);
}
}

React routing to endpoint but not rendering content

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>
);
}

ReactJS Routing Page Refresh

Currently using ReactJS to construct a small web app. I have the following parent function:
const Main = () => {
return (
<div className="dialog-base">
<BrowserRouter>
<Switch>
<Route exact path="/login" component={Login}></Route>
<Route exact path="/login/forgot_password" component={ForgotPwd}></Route>
<Route exact path="/login/reset_password/:key" component={ResetPwd}></Route>
<Route exact path="/portal" component={Portal}></Route>
</Switch>
</BrowserRouter>
</div>
);
}
and the following is the "Portal" component:
class Portal extends React.Component {
render = () => {
return (
<BrowserRouter basename="/main">
<div className="navmenu">
<NavLink to="messaging" activeClassName="selected">Messaging</NavLink>
<NavLink to="files" activeClassName="selected"></NavLink>
<NavLink to="payledger" activeClassName="selected"></NavLink>
</div>
<div className="apparea">
<Switch>
<Route path="/messaging" component={Messaging}></Route>
<Route path="/files" component={Files}></Route>
<Route path="/payledger" component={PayLedger}></Route>
</Switch>
</div>
</BrowserRouter>
);
}
}
When the portal component is loaded and I refresh the web page, the page goes blank. I am assuming that this has something to do with the nested routing? Any help on how to fix it would be much appreciated.
You don't need two <BrowserRouter />. Just define one <BrowserRouter /> in your top level component.
In react-router-dom v4+ the <Route /> is just like a regular component and you can use it inside your components to render UI when the path matches the URL.
Here is the working codesandbox example.
Make sure not to put exact on your parent <Route /> because when you have child routes like /main/messaging the <Route exact path="/main" /> never gets to render and therefore children of that route can't be rendered also.
You keep your <Main /> component as is but remove the exact from the <Route path='/portal' /> and change the <Portal />.
class Portal extends React.Component {
render = () => {
return (
<React.Fragment>
<div className="navmenu">
<NavLink to="/portal/messaging" activeClassName="selected">Messaging</NavLink>
<NavLink to="/portal/files" activeClassName="selected"></NavLink>
<NavLink to="/portal/payledger" activeClassName="selected"></NavLink>
</div>
<div className="apparea">
<Switch>
<Route path="/portal/messaging" component={Messaging}></Route>
<Route path="/portal/files" component={Files}></Route>
<Route path="/portal/payledger" component={PayLedger}></Route>
</Switch>
</div>
</React.Fragment>
);
}
}

Using Header globally in react using react-router-dom

I am currently using react-router-dom to create navigation within my web app.
My index.js and App.js look like:
Index.js
ReactDOM.render(
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>,
document.getElementById('root')
);
App.js
class App extends React.Component {
render() {
return (
<BrowserRouter>
<div>
<Route exact path ='/' component={Home} />
<Route path ='/container' component={Container} />
<Route path ='/profile' component={ProfilePage} />
</div>
</BrowserRouter>
);
}
}
I idea was that if Home contains the header and the sidebar, it would also keep it for other components like Container and ProfilePage.
My Home's render looks like:
render() {
return (
<div>
<Header />
<div className="App">
<Sidebar />
<Container className="container-comp" />
{this.renderLoggingOutput()}
</div>
</div>
);
}
But when I Link to /profile, it just shows me the ProfilePage component without the header and the sidebar.
Any help?
Put your header outside the routes:
class App extends React.Component {
render() {
return (
<BrowserRouter>
<Header /> <-------- place here or outside the routes at a minimum
<div>
<Route exact path ='/' component={Home} />
<Route path ='/container' component={Container} />
<Route path ='/profile' component={ProfilePage} />
</div>
</BrowserRouter>
);
}
}
I have a similar structure in one of my apps.
the routes look like this:
class App extends Component {
render() {
return (
<BrowserRouter>
<div className="App">
<Navbar />
<Switch>
<Route exact path='/' component={Dashboard}/>
<Route path='/character/:id' component={CharacterDetails}/>
<Route path='/encounter/:id' component={Encounter}/>
.........
</Switch>
</div>
</BrowserRouter>
);
}
}
export default App;
The only job of a route is to mount a component. If you want omnipresent components across all routes, treat the routes as children to a base component.
class App extends React.Component {
render() {
<div>
<Header />
<Sidebar />
{this.props.children}
</div>
}
}
const Routes = () => (
<App>
{/* your routes here */}
</App>
)

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>
);
}
}

Categories

Resources