React-router: components don't render unless refreshed - reactjs

I have a simple App component with Links to a User index and a Cache index (for a geocaching app). My Links render fine, and when clicked they change the path in the address bar, but nothing changes in the DOM until I refresh the page, at which point the page looks the way it should. What's going on here, and what's the conventional way of dealing with it? I am using Redux as well, if that makes any difference. The following is all of the JSX returned by my App component:
<div>
<nav>
<Link to="/caches">Caches</Link>
<Link to="/users">Users</Link>
</nav>
<div>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/users" render={() => <div><UserList users={this.props.users}/></div>}/>
<Route path="/caches" component={CacheList}/>
</Switch>
</div>
</div>

Its a common issue with react-router-4.
use {pure: false} in react-redux connect or use withRouter HOC.
React router 4 does not update view on link, but does on refresh

Related

Set nested links with React Router

I have a question about the React Router.
Now, I have a webpage with that looks like this:
As you can see there is another link on the page called "Custom Hooks".If I click on it, it will be shown something like this:
What I want now is to go to the a new page which the link shown in the image above, where the page will only shown me the "Example" and not the "This is UseState function" text.
In my code:
With my code, it cannot performs the route that I want to.
How can I fix this?
Thank you
This is happening because you seem to have misunderstood how the Switch component works. Think of it as a way of selecting what component to render based on the url. In the above code snippet,
<Link to="/Homepage"><Button>Back to Homepage</Button></Link>
<h1>This is UseState Function</h1>
<div>Example</div><Link to="/UseStatePage/UseStateFunction">Custom Hooks</Link>
is not under , meaning that whenever UseStateWebpage component is rendered, the Link, h1 and div with 'This is UseState Function' will always be rendered. If you want it to be rendered optionally based on the URL, there are multiple ways to achieve it. One way is as follows.
<Router>
<Switch>
<Route path="/UseStatePage" exact render={
()=>{
return(
<React.Fragment>
<Link to="/Homepage"><Button>Back to Homepage</Button></Link>
<h1>This is UseState Function</h1>
<div>Example</div><Link to="/UseStatePage/UseStateFunction">Custom Hooks</Link>
<React.Fragment>
)
}
}/>
</Switch>
<Switch>
<Route path="/UseStatePage/UseStateFunction" exact component={UseStateFunction}/>
<Switch>
<Router>
Neither the h1 nor div with example text are rendered into a route so they will always be rendered. Render the "homepage" content into its own route, something like the following.
function useStateWebPage() {
return (
<Router>
<Link to="/Homepage">Back To Homepage</Link>
<Switch>
<Route
path="/UseStatePage/UseStateFunction"
component={UseStateFunction}
/>
<Route path="/Homepage>
<h1>This is UseState function</h1>
<div>
Example
<Link to="/UseStatePage/UseStateFunction">custom Hooks</Link>
</div>
</Route>
</Switch>
</Router>
);
}

Problems with React-Router

So basically, I have a problem with react router not rendering my SystemSidebar. I want to scroll through my SystemSidebar components, but my problem is when I press on 'LinkSoundIcon' it redirects me to 'a new page' but that page doesnt render my systemSidebar . I want when I press on any of the links of my sidebar that my sidebar remains
import React from 'react'
import './SystemSidebar.css'
import SoundIcon from '#material-ui/icons/Computer';
import ComputerIcon from '#material-ui/icons/Computer';
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom';
import Sound from './Sound';
import Computer from './Computer;
const SystemSidebar=()=> {
return (
<div className='system'>
<div className="sidebar">
<Link to='Sound'><VolumeUpIcon /></Link>
<h4> Sound</h4>
<Link to='Computer'><ComputerIcon /></Link>
<h4> Computer</h4>
</div>
</div>
);
};
import React,{Component} from 'react'
import Sound from './Sound';
import Computer from './Computer';
import SystemSidebar from './SystemSidebar';
class MainSystem extends Component {
render(){
return (
<div className="MAIN">
<BrowserRouter>
<SystemSidebar />
<Switch>
<Route exact path="/" component={SystemSidebar} />
<Route exact path="/Sound" component={Sound}/>
<Route exact path="/Computer" component={Computer}/>
</Switch>
</BrowserRouter>
</div>
);
}
}
export default MainSystem;
<Link to='/Sound'><VolumeUpIcon /></Link>
answer of your first problem and second if you want to access sidebar in each component then don't put it in switch route , simply put it outside the routing... or if u want to access it with specific route then try using nested routing
Okay, so it seems a little wonky with your copy pasting (I hope this is just a problem that stems from copy and pasting and it's not like that in your code). But your Problem is here:
<Route exact path="/Sound" component={Sound}/>
You're saying here that the route should be EXACTLY http://<your root uri>/Sound
You should also use this exact route in the link if you want to hit it, this means you need to have the slash there:
<Link to='/Sound'><VolumeUpIcon /></Link>
Update:
So according to your comment you want the sidebar to stay when you click a link. In this case, take a look at your code:
<Switch>
<Route exact path="/" component={SystemSidebar} />
<Route exact path="/Sound" component={Sound}/>
<Route exact path="/Computer" component={Computer}/>
</Switch>
You define here that the component SystemSidebar will only be loaded when you're at the Root directory ("/") of your App. It will be unloaded when you change that directory, for example, to "/Sound". SystemSidebar will be unloaded and Sound will be loaded instead.
Since your Sidebar should always be shown, it needs to be in your Main App and outside of your actual Router logic. Remember what the React Router does: It switches out components depending on which directory (which Sub-URL) you're in. It's best practice to have a Sidebar, an App Bar or similar things that are always there to be their own components. Your actual content should live in a separate container, where the needed component can be swapped out by the Router if need be. So something like this:
class MainSystem extends Component {
render(){
return (
<div className="MAIN">
<SystemSidebar />
<div className="ContentContainer">
<BrowserRouter>
<Switch>
<Route exact path="/Sound" component={Sound}/>
<Route exact path="/Computer" component={Computer}/>
{/* Route "/" should be last because it acts as fallback! */}
<Route exact path="/" component={StartPage} />
</Switch>
</BrowserRouter>
</div>
</div>
);
}
}
That's pretty basic but I hope you get the gist of it.
Also, I'd encourage you to take a look at an UI framework like Material UI for example. It already provides components ready for use (like your Sidebar which is called Drawer there), it's mobile first and easy to use with responsive design.

how to open (after clicking) react component in new page

Hi every one I am trying create new page in react in this way.
I Have component which name is "SolutionsSectionsPic".
And I want after clicking on that component open another component (which name is "SItem" ) in new page (not in new tab). I am writing something like this
<Router>
<Link to="/ecommerce">
<SolutionsSectionsPic />
</Link>
<Route path="/ecommerce" component={SItem} />
</Router>
But when I click on "SolutionsSectionsPic" component, my "SItem" component immediately appears under "SolutionsSectionsPic" component.
How can I fix it?
This is because your Link will always be rendered no matter what. A solution to this is wapping your Link in a Route, that way it will only be rendered on that route.
<Router>
<Route path="/" exact>
<Link to="/ecommerce">
<SolutionsSectionsPic />
</Link>
</Route>
<Route path="/ecommerce" exact component={SItem} />
</Router>
You also see that I use exact, that means that only / will be valid, otherwise all routes that start with / will be valid.

Difficulty with blocking and react-router

I am running into the issue where the URL is changing but the page is not when using react-router and redux. I have attempted the solutions from the docs involving location and using withRouter (https://reacttraining.com/react-router/web/guides/dealing-with-update-blocking), however, I believe the issue stems from the fact that I am trying to reload the same component and then use the params from the URL to make an API call that then re-renders the component with the retrieved values.
<Route path="/video/:id" exact={true} component={VideoDisplay} />
and then from within the VideoDisplay component:
<Link to={`/video/${props.id}`}>
I duplicated the component, which gets around the issue of trying to link to a route's own component:
<Route path="/video/:id" exact={true} component={VideoDisplay} />
<Route path="/video/test/:id" exact={true} component={VideoDisplayTwo} />
<Link to={`/video/test/${props.id}`}>
<Link to={`/video/${props.id}`}>
This works, but I am looking for a more elegant solution.

React router 4 does not update view on link, but does on refresh

I am using the following simple nav code
<Router>
<Switch>
<Route exact path='/dashboard' component={Dashboard} />
<Route path='/dashboard/accounts' component={AccountPage} />
</Switch>
</Router>
<NavLink exact to={'/dashboard'}
disabled={this.props.item.disabled}
activeClassName='active'>
<NavLink exact to={'/dashboard/accounts'}
disabled={this.props.item.disabled}
activeClassName='active'>
The URL changes but the view does not. It does however change when I refresh the page or manually go to that URL.
You can also use the:
import { withRouter } from 'react-router-dom';
And then on your export default, you do like this:
export default withRouter(connect(mapStateToProps, {})(Layout));
Because when you have an export connect, you need to tell that that component will be using the router.
This is because react-redux connect method implements shouldComponentUpdate which will cause component not to render when props didn't change. And this is conflicting now with react-router 4.
To avoid it you can pass {pure: false} to connect as described in react-redux troubleshooting section.
Another way is to use withRouter HOC or pass location prop like described in DOCS.
I had my Navlinks in a stateless-component (or dumb component) and a container to control the collapse-state of my navbar.
after switching the navbar-container from PureComponent to Componentit solved the problem for me.
I have encountered this problem. I resolve it by add attribute key to component Switch with value is a location pathname and location search.
Have you tried making sure that your router tags wrap the entire chunk of code?
<Router>
<Switch>
<Route exact path='/dashboard' component={Dashboard} />
<Route path='/dashboard/accounts' component={AccountPage} />
</Switch>
<NavLink exact to={'/dashboard'}
disabled={this.props.item.disabled}
activeClassName='active'>
<NavLink exact to={'/dashboard/accounts'}
disabled={this.props.item.disabled}
activeClassName='active'>
</Router>
It looks odd, but including links into the <Router> propagates your path change to router components when you click the link and actually renders the component you are routing to. Just fixed a very similar problem myself.

Resources