I'm using react-router on a page with navbar and content.
const App = () => (
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/shape/:activeTab" component={Shapes} />
<Redirect from="/shape" to="/shape/triangle" />
</Switch>
</Router>
);
-- Shapes
class Shapes extends React.Component {
getActiveTab() {
switch (this.props.match.params.activeTab) {
case 'triangle':
return Triangle;
case 'circle':
return Circle;
case 'square':
return Square;
default:
return Triangle;
}
}
render() {
return (
<div className="wrapper">
// this is where the navbar renders.
<ul>
<li>
<NavLink exact to={`/shape/triangle`}> Triangle </NavLink>
</li>,
<li>
<NavLink exact to={`/shape/circle`}> Circle </NavLink>
</li>,
<li>
<NavLink exact to={`/shape/square`}> Square </NavLink>
</li>,
</ul>
// this is where the content renders.
<div className="content">
{
this.getActiveTab().data.map(tuple =>
<div>
{tuple.description}
</div>,
)
}
</div>
</div>
);
}
};
Now, when I click localhost:8080/shape I get redirected to proper page with navigation.
Also the navigation works properly (i:e. clicking on Triangle redirects me to localhost:8080/shape/triangle)
But, when I try to access the page localhost:8080/shape/triangle directly, I get a 404!
It works only when I access the /shapes page first and then use the navigation.
What do I need to address here to make sure I can route to shape/* pages.
Note: I'm referring https://reacttraining.com/react-router/web/api/Switch
Related
I am facing a very weird issue. In my react app, the navbar is something like:
<ul>
<li>
<a href={"/Marketplace"}>Marketplace</a>
</li>
</ul>
I have a simple login feature in my app which redirects the user to the homepage after logging in. After I log in, the href value in the above anchor tag disappears. I can't seem to understand why this is happening. basically, the same code block now becomes:
<ul>
<li>
<a href>Marketplace</a>
</li>
</ul>
If you want to allow users to link to other pages on click, Use Link tag !
for more help react-router-dom
import React from "react";
import { BrowserRouter, Link, Route, Switch } from "react-router-dom";
const Marketplace = () => {
return <div>This is the Market place</div>;
};
const Home = () => {
return <div>This is the home page</div>;
};
export default function App() {
return (
<div className="App">
<BrowserRouter>
<nav>
<div>
<Link to="/">Home</Link>
</div>
<div>
<Link to="/Marketplace">Marketplace</Link>
</div>
</nav>
<Switch>
<Route path="/Marketplace">
<Marketplace />
</Route>
<Route path="/" exact>
<Home />
</Route>
</Switch>
</BrowserRouter>
</div>
);
}
use Link instead of Anchor Tag if you are using react router
import { Link } from "react-router-dom";
<Link to="/Marketplace">Marketplace</Link>
I'm building a website with React and I would like my navbar to have a different background color depending on the current route. My App.js looks like this:
class App extends React.Component {
render() {
return (
<Router>
<div className="App">
<div className="Navbar" >
<Navbar />
</div>
<div className="Content">
<Route path="/" exact render={() => <LandingPage />} />
<Route path="/about" exact render={() => <AboutPage />} />
<Route path="/contact" exact render={() => <ContactPage />} />
</div>
</div>
</Router>
);
}
}
Suppose I want a transparent background on the Home ("/") page, but a solid color everywhere else, what is the best way to go about changing the background property in <Navbar />'s CSS to achieve what I want?
Suppose I stored the CSS properties I'd like to change in this.state, and then call a function to change these whenever there is a route change?
You can use context api for changing the background color of any of your components. So, you just need to define a context value based on the different urls.
I'm new react user, when i see react-router docs, I confused.
let me show,
first, the docs url: https://reacttraining.com/react-router/web/example/route-config
I simplify like this
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
const routes = [
{
path: "/",
component: Sandwiches
},
{
path: "/tacos",
component: Tacos
}
];
export default function RouteConfigExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">/</Link>
</li>
<li>
<Link to="/tacos">tacos</Link>
</li>
</ul>
<Switch>
{routes.map((route, i) => (
<RouteWithSubRoutes key={i} {...route} />
))}
</Switch>
</div>
</Router>
);
}
function RouteWithSubRoutes(route) {
return (
<Route
exact
path={route.path}
component={route.component}
/>
);
}
function Sandwiches() {
return <h2>/</h2>;
}
function Tacos() {
return (
<div>
<h2>Tacos</h2>
</div>
);
}
now, when i click / show /, but click Tacos show nothing.
what expect, click / show /, and click Tacos show Tacos.
I resolve by these
// first, do not use component wrap
export default function RouteConfigExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">/</Link>
</li>
<li>
<Link to="/tacos">tacos</Link>
</li>
</ul>
<Switch>
{routes.map((route, i) => (
<Route
key={i}
exact
path={route.path}
component={route.component}/>
))}
</Switch>
</div>
</Router>
);
}
// second, do not use Switch
export default function RouteConfigExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">/</Link>
</li>
<li>
<Link to="/tacos">tacos</Link>
</li>
</ul>
{routes.map((route, i) => (
<RouteWithSubRoutes key={i} {...route} />
))}
</div>
</Router>
);
}
It bothered me for a long time, now I'm dying to know why, Please tell me in detail, and thanks so much...
In addition, My English is not pretty, understanding...
Switch components only valid children are Route and Redirect, so even though another react component renders a Route it won't work quite in the same way.
Switch children
All children of a <Switch> should be <Route> or <Redirect> elements.
Only the first child to match the current location will be rendered.
Edit
While wrapped Route components can still render, as "grand-children" descendants, it appears that route props are only applied at the root Switch level.
In the following Switch, even though RouteWithSubRoutes specifies the exact prop, RouteWithSubRoutes in the react DOM does not, so only the first element is returned (coincidentally the home "/" route).
<Switch>
{routes.map(route => (
<RouteWithSubRoutes key={route.path} {...route} />
))}
</Switch>
This following Switch is identical to the above except for specifying exact prop, and this works as expected.
<Switch>
{routes.map(route => (
<RouteWithSubRoutes key={route.path} exact {...route} />
))}
</Switch>
/Edit
It sounds like you have a two-part question, why both resolutions work.
The first attempt at fixing by rendering a Route directly succeeds by specifying the exact prop on all routes within the Switch, which only matches and renders the first matching Route or Redirect. When the path is exactly "/" then that component renders, and when it is exactly "/tacos" then that component renders.
The second attempt you render all the routes just right in the Router, which matches and renders all matching routes, but since you specify, again, the exact prop, it matches a single route and works.
Demo
I'm try to use react-router with react-three-fiber. The issue is the <Switch> components lose their context when added inside a react-three-fiber <Canvas> element. To fix this I can wrap the switch inside a <Router> inside the Canvas. And the routes work as expected when manually typing the url. However, the ` elements now seem to reference another Router and don't work when clicked.
Is there a way to make the elements inside and outside the <Canvas> reference the same router?
https://codesandbox.io/s/reach-router-starter-v1-9qcjc
const App = ({ router }) => {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
<hr />
<Canvas>
<Plane color="black" position={[-5, 0, 0]} />
<Router>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
</Switch>
</Router>
</Canvas>
</div>
</Router>
);
};
const Home = () => <Plane color="red" position={[0, 0, 0]} />;
const About = () => <Plane color="green" position={[0, 0, 0]} />;
const Dashboard = () => <Plane color="blue" position={[0, 0, 0]} />;
You can use npm i wouter instead of react-router-dom https://www.npmjs.com/package/wouter
Wrap everything as you normally would using react-router-dom but use wouter instead. Note that top level Router component is fully optional.
App.js :
import Nav from './Nav'
import { Router, Switch, Route } from 'wouter';
make App.js a class component and structure like so:
<Nav />
<Router/>
<Switch />
<Route exact path="/somelink" component={Somecomponent}/>
<Switch />
<Router/>
export default App;
Nav.js component:
import { Link } from 'wouter'
const Nav = () => {
return (
<nav className="navigation">
<ul>
<li>
<Link to="/somecomponent">...</Link>
</li>
</ul>
</nav>
)
}
export default Nav;
I am hoping someone can confirm for me the expected behavior of react-router for nested routes. I would like to have base routes like 1) /route1 and then nested routes like 2) /route1/nested1 and 3) /route1/nested1/also. Is it possible for those nested routes to render child components without re-rendering that first route's component? Can someone confirm or possibly show a small code sample in which nested routes do not cause the parent component to re-render if you have done this successfully? Many thanks in advance. I believe this is not possible, and I astonished that react-router would be designed this way, since this is not how React itself works. I had thought perhaps the updates to the props.history caused the re-render, but if so, it does this whether or not those props are explicitly given to the component.
I have looked at the official docs and many pages of comments and questions online. Some folks seem say they were able to get this behavior while others say they simply cannot. Questions about this on the react-router GitHub were closed without being answered, since it was not considered a bug.
import React from 'react'
import { Link, Switch, Route, BrowserRouter as Router } from 'react-router-dom'
class Home extends React.Component {
render() {
return <div>Home</div>
}
}
class Route1 extends React.Component {
render() {
console.log('Route1 RENDER')
console.log('route1 props', this.props.history)
return (
<div>
<div>Route1</div>
<ul>
<li>
<Link to={'/route1/276364554643'}>nested route 1</Link>
</li>
<li>
<Link to={'/route1/276364554643/also'}>also</Link>
</li>
</ul>
<Route
exact
path={'/route1/:param_1'}
render={() => <NestedRoute1 />}
/>
<Route
exact
path='/route1/:param_1/also'
render={() => <Also />}
/>
</div>
)
}
}
class NestedRoute1 extends React.Component {
render() {
console.log('nested route history', this.props.history)
return <div>Nested Route Component</div>
}
}
class Also extends React.Component {
render() {
return <div>Also</div>
}
}
class Two extends React.Component {
render() {
return <div>Two</div>
}
}
class Three extends React.Component {
render() {
return <div>Three</div>
}
}
class App extends React.Component {
render() {
console.log('APP RENDER')
return (
<div className='App'>
<Router>
<div>
<ul>
<li>
<Link to='/'>home</Link>
</li>
<li>
<Link to='/route1'>route1</Link>
</li>
<li>
<Link to='/two'>two</Link>
</li>
<li>
<Link to='/any-other'>other</Link>
</li>
</ul>
<Switch>
<Route exact path='/' component={Home} />
<Route
path='/route1'
render={() => <Route1 />}
/>
<Route path='/two' component={Two} />
<Route path='/:other' component={Three} />
</Switch>
</div>
</Router>
</div>
)
}
}
export default App
EXPECTED: react-router should allow additions and changes to nested routes without an re-rendering parent components (the nested routes should match the component tree and behave the same way react behaves where changes in children do not trigger changes higher in the tree)
ACTUAL: changes to nested routes cause the parent component to re-render