react router not showing component on url update - reactjs

probably a simple question for most but, why isn't my component rendering when my url updates, when I update the url manually it works but the links i'm using do not?
I have included my links component below, the display bar should display as a nav (so on every route) but the Newcase component should only display on its specified route. I have tried using the exact prop on it.
import React, { Component } from 'react'
import { BrowserRouter as Router, Route,Link } from 'react-router-dom';
export default class DisplayBar extends Component {
render() {
return (
<div>
<Router>
<Link to="/">home</Link>
<Link to="/form">form</Link>
</Router>
</div>
)
}
}
and here is my router in my main app.js
render(){
return (
<Router>
<Route path = '/' component ={DisplayBar} />
<switch>
<Route exact path='/form' component = {NewCase} />
</switch>
</Router>
);
}

You don't need to wrap your links with Router, Remove Router
<Link to="/">home</Link>
<Link to="/form">form</Link>
and also put <Route path = '/' component ={DisplayBar} /> inside switch
<switch>
<Route path = '/' component ={DisplayBar} />
<Route exact path='/form' component = {UserAdd} />
</switch>

Related

Why child route won't render without the parent route rendering?

I am trying to navigate to /movie/:title on which I am rendering a new page. But it only renders if my movie page i.e /movie renders, but I don't want my movie page to be mounted on navigating to /movie/:title. I only want it as part of the path. Making the /movie path exact doesn't work as /movie/:title wouldn't render with /movie as exact.
App.js
class App extends React.Component {
render() {
return (
<div>
<Header />
<Route path='/movies' component={Movies} />
<Route path='/tvshows' component={TvShow} />
</div>
)}
Movie.js
return (
<div className="movies">
<Route path={`${match.path}`} render={(props) => <CollectionGrid movies/>} />
<Route path={`${match.path}`} render={(props) => <CollectionOverview movies/>} />
<Route path={`${match.path}/:title`} component={ItemPage} />
</div>
);
A couple of notes. Conventionally, you should keep all your routes in a single router, thus making it easier to navigate and identify your application.
Organize your Router like this:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import Home from "./Home";
import Movies from "./Movies";
import ItemPage from "./ItemPage";
const App = () => {
return (
<BrowserRouter>
<div>
<Switch>
<Route path="/" component={Home} exact />
<Route path="/movies/:title" component={ItemPage} />
<Route path="/movies" component={Movies} />
</Switch>
</div>
</BrowserRouter>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Additionally, to resolve your solution, you would need the Switch component, which is available in react-router-dom. The Switch component, will look through a list of Routes and will only render the FIRST Route who's path string is included within the URL string.
In the list above we have 3 Routes. If your URL is "/movies/blah", it will only render the ItemPage component, because that Route's path was matched first within the list.
We moved the "/movies/:title" Route before the regular "/movies" for this very reason. If the "/movies" Route appeared first in the list and if your URL was "/movies/blah", it would still satisfy the "/movies" Route. That means Switch would only render Movies component, which is not what you want.
See working sandbox: https://codesandbox.io/s/hopeful-bogdan-lzl76
you are not able to access to match direct in this app the match is found in this .props.match
you cand used it in
const App({match})
then when you need to used it should
<Route path={`${match.path}`} render={(props) => <CollectionGrid movies/>} />
look to this example and explain

Render react component based on dynamic routes

I'm struggling to render a component based on routes from the React-Router. When the route is dynamic I can't seem to figure out a way to match the route.
I have created a component "Navbar" which I want to render only on specific routes. For this purpose I created a separate component "Tracker" which matches the route and renders the "Navbar" component.
Tracker.js snippet:
class Tracker extends Component {
render() {
var NavVisible =
this.props.location.pathname === "/feed" ||
this.props.location.pathname === "/explore" ||
this.props.location.pathname === "/chatroom" ||
this.props.location.pathname === "/username" ? (
<Navbar />
) : null;
return <div>{NavVisible}</div>;
}
}
Suppose if I have to display the Navbar component in "feed/(some_dynamic_path)", how should I write the condition?
A solution would be greatly appreciated.
Thanks.
Edit: App.js
import React, {Component} from 'react';
import {BrowserRouter, Switch, Route} from 'react-router-dom';
class App extends Component{
render(){
const DefaultContainer = () => (
<div>
<Route path='/home' component={ft}/>
<Route path='/explore' component={exp}/>
<Route path='/compose' component={add}/>
<Route path='/chatroom' component={msg}/>
<Route path='/user' component={usrpro}/>
</div>
)
return (
<BrowserRouter>
<div className="App">
<Tracker/>
<Switch>
<Route path='/' exact component={Splash}/>
<Route exact path="/(compose)" component={noNavContainer}/>
<Route exact path="/(newtext)" component={noNavContainer}/>
<Route path="/(login)" component={login}/>
<Route component={DefaultContainer}/>
</Switch>
</div>
</BrowserRouter>
);
}
}
export default App;
You can try something like:
this.props.location.pathname === '/feed/' + this.props.params.id
Might get you started: https://jaketrent.com/post/access-route-params-react-router-v4/
You can include Routers for various urls like this in your app.
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
class App extends React.Component {
render () {
return (
<Router>
<Home>
<Switch>
<Route path='/feed/:path_variable' component={Navbar} />
</Switch>
</Home>
</Router>
)
}
}
Also In Navbar Component, You will get access to this.props.match.params.path_variable whose value changes based on the URL.
Read more about it in this nicely written article.
https://scotch.io/courses/using-react-router-4/route-params

How to change the page and change only one component, not the entire html

I'm starting in React and I'm curious about about if have any way to change a page without reload all the html, changing only a content component for example.
I know that there is a way to change the component without change the url but I thought that if the url change too the application would be better.
React Router is the exact thing you're looking for
Here, how you can achieve what you're looking for.
First, wrap your app with BrowserRouter
import { BrowserRouter } from "react-router-dom";
import React from 'react';
class App extends React.Component {
return (){
return (
<BrowserRouter>
<SomeComponent />
</BrowserRouter>
)
}
}
Now just use the Route and Link. Route told the application which component to render on the basis of the current route and Link changes the URL without reloading the whole page
import { Route, Link, Switch } from "react-router-dom";
import React from 'react';
import {Circle, Square} from './someFileWithComponents';
class SomeComponent extends React.Component {
render(){
return (
<div>
<Link to='/circle' >Circle</Link>
<Link to='/square' >Square</Link>
<Switch>
<Route path='/circle' component={Circle} />
<Route path='/square' component={Square} />
</Switch>
</div>
)
}
}
React Router is what you looking for
const AppRouter =()=>(
<BrowserRouter>
<div>
<Header/>//where Header components contains the navigation
<Switch>
<Route path="/" component={BookListPage} exact={true} />
<Route path="/create" component={AddBookItem} />
<Route path="/edit/:id" component={EditBookItem} />
<Route path="/help" component={HelpPage} />
<Route component={NotFoundPage} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;

React Routing still showing root component even after using exact

I am still a newbie to React. So here I am rendering the root component with two routes: Home and About located in functional components: home.js and about.js respectively. However, even after using exact attribute and , the root component keeps on rendering above. I still cannot figure out how to not render the root component when I am redirecting to any of the mentioned routes?
Heres the live demo: https://codesandbox.io/s/vmz6zwq0k7
The Route component is acting like a "placeholder" for the component you want to render when the URL matches. everything above it (parents and siblings) wont get affected.
Given this code example:
render() {
return (
<BrowserRouter>
<div className="App">
<Link to="/home"> Home </Link>{" "}
|
<Link to="/about"> About Us </Link>{" "}
<div>
<Route exact path="/home" component={Home} />
<Route exact path="/about" component={About} />
</div>
</div>
</BrowserRouter>
);
}
This line of code:
<Route exact path="/home" component={Home} />
Is only a "placeholder" for the Home component. It won't render anything only when the path is matching "/home".
When the path will match, the Route component will render the passed component, The Home component in this case.
It will not affect the entire app tree, and for a good reason!
If the entire app would get re-rendered and replaced with the Home component you would loose the navigation links.
I had the same problem looking at the react-routing getting started portion here. https://reactrouter.com/web/guides/quick-start
I placed my Router/BrowserRouter in my App component. Instead place the router in your index.js file like so
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>,
document.getElementById('root')
);
Then your app component can look like so and the root route wont be matched if about or users is matched.
import React from "react";
import {
Switch,
Route,
Link
} from "react-router-dom";
export default function App() {
return (
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</div>
);
}
function Home() {
return <h2>Home</h2>;
}
function About() {
return <h2>About</h2>;
}
function Users() {
return <h2>Users</h2>;
}

How to link to Routes inside the component rendered by another Route with React Router

i'm trying to use react router in my reactjs app. And I encountered this problem:
This is what i'm trying to do:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import About from '../Pages/About';
import Home from '../Pages/Home';
import Topics from '../Pages/Topics';
import LinkTest from '../Pages/LinkTest';
class AppRouter extends Component {
render() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/home">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
<Route path="/home" component={LinkTest}/>
</ul>
<hr />
<Route path="/home" component={Home}/>
<Route path="/about" component={About} />
<Route path="/topics" component={Topics} />
</div>
</Router>
);
}
}
export default AppRouter;
Ignore "about" and "topic" component, when I click on "Home" link, it should target 2 routes, one will render "LinkTest" and the other renders "Home".
This is what inside "LinkTest":
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
class LinkTest extends Component {
render() {
const {match}=this.props;
return (
<div>
<Link to={`${match.url}/Test`}>Link To Test</Link>
</div>
);
}
}
export default LinkTest;
And inside my "Home" component:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Test from './Test';
class Home extends Component {
render() {
const {match} = this.props;
console.log(match.url);
return (
<Router>
<div>
<h2>
Hello from Home page
<Link to={`${match.url}/Test`}>Link To Test</Link>
<Route path={`${match.url}/Test`} component={Test}/>
</h2>
</div>
</Router>
);
}
}
export default Home;
However:
When i click on the link inside "LinkTest" component (which was rendered earlier), the url on the browser is shown "http://localhost:3000/home/Test", but nothing happens.
When i clicked on the link inside "Home" component, (which was rendered the same time as the "LinkTest" using the same link), it showed the same url on the browser: "http://localhost:3000/home/Test", only this time it rendered the "Test" component.
Why does this happen? (what i want to achieve is I want to use the link inside "LinkTest" to render "Test" component inside "Home" component, or something similar).
I hope this is clear enough.
You can do it in following way:
<Route exact path='/a' component={A} />
<Route path='/b' component={B} />
// Following should be router inside Component B
<Route exact path='/b/abc' component={OtherComponent}
If you want I've prepared few react-router 4 examples. These are hosted here. https://github.com/SandipNirmal/react-router-examples
If you need Nested routing inside ComponentB you should add Links for those Routes as well. And use match.url and match.path to build the nested Links and Routes.
const ComponentB = ({ match }) => {
return (
<div>
<div>
<ul>
<li><Link to={`${match.url}/c`}>Component C</Link></li>
// more Links
<li><Link to={`${match.url}/css`}>CSS</Link></li>
<li><Link to={`${match.url}/react`}>React</Link></li>
</ul>
</div>
<div>
<Route path={`${match.path}/c`} component={ComponentC} />
// more nested Routes
<Route path={`${match.path}/css`} render={() => { return <h1>CSS</h1> }}/>
<Route path={`${match.path}/react`} render={() => { return <h1>React</h1> }}/>
</div>
</div>
);
}
Nested routing
Components created via Route will automatically be passed the following prop objects: match, location and history.
Using match you can implement nested Routes. The match object contains the following properties:
params — (object) Key/value pairs parsed from the URL corresponding
to the dynamic segments of the path
isExact — (boolean) true if the entire URL was matched (no trailing characters)
path — (string) The path pattern used to match. Useful for building nested Routes
url — (string) The matched portion of the URL. Useful for building
nested Links
Reference
https://medium.freecodecamp.org/beginners-guide-to-react-router-4-8959ceb3ad58
https://medium.com/#pshrmn/a-simple-react-router-v4-tutorial-7f23ff27adf

Resources