React Switch not rendering different pages - javascript

I got a react app that got a component that renders my HomePage. I decided to create another component so i can switch between pages on the site. For the HomePage it works when i enter the site, but clicking on navlinks is not working, also if i type the url /contacto i am not getting the render of Contact component, i get the render of the HomePage component, it's not switching between them.
class ContactPage extends Component {
render() {
return <div>HOLA</div>;
}
}
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={HomePage} />
<Route path="/contacto" component={ContactPage} />
</Switch>
</BrowserRouter>
);
}

Add exact to your HomePage route:
<Route exact path="/" component={HomePage} />
This is because the path / still matches in a non exact way to /contacto and the router renders the first match (that being your HomePage).
By adding exact, you're telling it not to match partial matches.

Related

Should I be using functions instead of classes for pages in ReactJS?

I've noticed React Router DOM (v6) is now using functions in their help guides in regards to pages instead of using classes.
Previously used classes like so:
export class Login extends React.Component {
render() {
return <p>test</p>
}
}
However, after trying the latest version of React Router DOM I would receive an empty page for the navigation route.
import {Login} from "./js/components/Auth/Login";
function App() {
return <h2>Test</h2>
}
if (document.getElementById('app')) {
ReactDOM.render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="/login" component={() => <Login />} />
</Routes>
</BrowserRouter>, document.getElementById('app'))
}
App works fine ('/' route), but /login returns an empty page with no error..
Login refers to a class that uses render() and returns <p>test</p>
Am I doing something incorrectly? Are libraries leaning towards functions instead of class components?
This guide seems to be only using functions for components.
https://reactrouter.com/docs/en/v6/getting-started/tutorial
Class vs Function components is irrelevant in RRDv6, they simply render React components specified as JSX, not as a reference to a component, and not as a function returning JSX. There is also no render or component props, the Route components now use only element to render the route components.
<Routes>
<Route path="/" element={<App />} />
<Route path="/login" element={<Login />} />
</Routes>

Render child component over parent

I need to render component with another route but this component must not cover all page. For example, I clicked on some question from stackoverflow list, and than I will receive animate from right to left modal, and I need to change route also
React router (I am using V4)
export default (
<Switch>
<App>
<Route exact={true} path="/" component={App} />
<Route exact={true} path="/product/:id" component={Product}/>
</App>
</Switch>
);
My product container looks like
export default function productContainer(ChildComponent) {
class ProductContainer extends Component {
render = () => {
return <ChildComponent/>
}
}
return ProductContainer;
}
And my product component
class Product extends Component {
render = () => {
return ("")
}
}
export default productContainer(Product);
When I emulate situation, which I describe above, my page fully rerendred and I don't see my App component Page
Have any idea, how I can resolve this issue?
People have asked how to render a modal as a route before in react-router without re-rendering (can't find the discussion right now). Essentially with react-router this is not possible. Each route change causes a re-render. That said, you can do what you want by nesting your routes.
Each component can return routes, so by using composition you can choose where to render any route.
For instance,
export default (
<Switch>
<App>
<Route path="/" component={App} />
</App>
</Switch>
);
Inside <App /> -
render() {
return (
<Something>
<PageHeader />
<Switch>
<Route path="/product/:id" component={Product}/>
</Switch>
</Something>
);
}
So you can see, if you were to add your routes inside the App component, they can all share a common page layout.
Remember: Any component can return multiple routes or just a single one inside a Switch! Switch will only render the first route that matches.
Also Remember: Routes inside a switch must be a direct child, you can't have Switch -> App -> Route, it must always be a direct child like Switch -> Route
Use render property instead of component in Route.
<Route exact={true} path="/" render={() => (
<div>
<App />
<Route exact={true} path="/product/:id" component={Product}/>
</div>
)} />

Deeplink routing is not working as intended with multiple routes

I am using react-router-dom#^4 and I am trying to render some deeply routed components. Here is a simplified version of my Base component.
export default function Base() {
return (
<Layout>
<Switch>
<Route exact path="/browse" component={Browser} />
</Switch>
</Layout>
);
}
This, in turn, will render the following component.
export default function Browser() {
return (
<Switch>
<Route exact component={ProjectPicker} />
<Route exact path=":projectId" component={ProjectDetail} />
</Switch>
);
}
While the root (/browse) does work, when I navigate into /browse/1 manually, it will fail. It essentially just renders nothing at all
Why is deeplinking failing here?
I think you need to add / in you path name
`<Route exact path="/:projectId" component={ProjectDetail} />`
see this official guide. https://reacttraining.com/react-router/web/example/url-params

React router appends page at last when routing

I have two components, {App} and {Blog}, when I was trying to route to Blog page from App, actually the Blog page content was appended at the last of App page. How can I jump to the blog page from App page?
Routing:
const routes = (
<BrowserRouter>
<div>
<Route path="/" component={App}/>
<Route path="blog" component={Blog}/>
</div>
</BrowserRouter>
);
Meteor.startup(() => {
ReactDOM.render(routes, document.querySelector(".render-target"));
});
Blog.js:
class Blog extends Component{
render(){
return(
<div>Blog</div>
);
};
}
export default Blog;
You need to use the Switch component from react-router. This will make sure that the first route matches inside.
<BrowserRouter>
<Switch>
<Route path="blog" component={Blog}/>
<Route path="/" component={App}/>
</Switch>
</BrowserRouter>
As you can see in the example, put the blog route before the /. If you put the / route as your first route it will match this one on any other route and stop there.
For more info, check out this piece

Can't make React-Router render two different components, always render root

I have these two components that are completely independent of each other. I want to render App when I enter / and render About when I go to /#/about
I got this piece of code (but I tested quite a few others):
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, Link, browserHistory } from 'react-router'
import App from './App';
import About from './About';
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={App} >
<Route path="/about" component={About} />
</Route>
</Router>
, document.getElementById('root')
);
I also tried something like
<Route path="/about" component={About} />
<Route path="/" component={App} />
And changed /about to /#/about, about
But it always render the "fallback" /, it always goes to this route, no matter what.
How can I make this app navigate properly to / and /about and render the App and the About components?
#edit
Assuming that my About component is broken, I removed the first Route and kept only the /about (kept only the /about Route) :
<Route path="/about" component={App} />
(I tried keeping About as well in a previous test) and also changed the /about to about and /#/about.
And I get this error on console:
"VM3651 bundle.js:30801 Warning: [react-router] Location "/#/about" did not match any routes"
#edit 2
I made a change, following the example #Dominic posted. I had to make some modifications to make sure both components would render. I added the {this.props.children} to all Components to understand what would happen.
//imports
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={About} >
<IndexRoute component={App} />
<Route path="/about" component={Other} />
</Route>
</Router>
,document.getElementById('root'));
The route http://localhost:3000/#/about is rendering:
> About > App
So it is rendering the IndexRoute, it is not getting caught by the /about.
And this is now exactly what I need, because I didn't want a root component, I wanted 2 routes to 2 different and isolated components. I need something like two sibling routes.
#edit
The About.js
import React, { Component } from 'react';
class About extends Component {
render() {
return (
<div>
About page
{this.props.children}
</div>
);
}
}
export default About;
Solution:
Since I'm using a HASH (#) in the URL, I should use hashHistory from React Router in the <Router history={hashHistory}>
You're confusing how routes work - About is a child of the App route, so in order to render About, it has to render App.
In other words your App component is the "shell" and all components under it render INSIDE it (via props.children).
You should add another route to render /.
import { ..., IndexRoute } from 'react-router'
<Route path="/" component={App} >
<IndexRoute component={Home} />
<Route path="about" component={About} />
</Route>
Your App does not contain route specific content, it would be something more like this:
<div id="app">
<nav>app navigation</nav>
<main class="route-content">{props.children}</main>
</div>
Docs: https://github.com/ReactTraining/react-router/blob/master/docs/guides/RouteConfiguration.md#adding-an-index
Those routes look correct to me. Are you getting any errors in the console? Maybe your About component is undefined and thus not rendering. Can you post your About component?

Categories

Resources