Is this how I should using react-router and nested routes in react-router-dom?
This code is working but I didn't fully understand the documentation so I want to be sure.
main.js:
const main = (props)=>(
<Header/>
{props.children}
);
app.js
const app = () => (
<Router>
<Route path="/main" children={(props) => (
<Main {...props}>
<Route path="section1" component={section1Component} />
<Route path="section2" component={section2Component} />
</Main>
)} />
</Router>
);
Related
function App() {
return (
<div className="App">
<main className="container">
<Routes>
<Route path="/Rentals" component={Rentals} />
</Routes>
</main>
</div>
);
}
the code is not working i get no routes matched location
The "No routes matched location '/'" error means that it cannot find the index path. Routes need to start at location "/" aka the index. Try something like this:
function App() {
return (
<div className="App">
<main className="container">
<Routes>
<Route index component={<default website here>} />
<Route path="/Rentals" component={Rentals} />
</Routes>
</main>
</div>
);
}
Alternatively, if you still want to start at the '/Rentals' page, you can do:
function App() {
return (
<div className="App">
<main className="container">
<Routes>
<Route path="/" element={<Navigate to="/Rentals"/>} />
<Route path="/Rentals" component={Rentals} />
</Routes>
</main>
</div>
);
}
Is there any way how to create two different pages starting with same sring - GuidePage and GuideDetailPage using react router?
My code doesn't work, after open /guide it shows GuidePage components, it's ok. But after open /guide/detail it shows GuidePage NOT GuideDetailPage.
What is wrong?
<Router history={history}>
<main>
<MenuHeader />
<Switch>
<Route path='/guide'>
<Route path='/' component={GuidePage} />
<Route path='/detail' component={GuideDetailPage} />
</Route>
<Redirect to='/home' />
</Switch>
<Footer />
</main>
</Router>
So I can use /guide-detail for GuideDetailPage but I want to use guide/detail.
In React Router 4, routes are dynamic instead of static, you don't need to declare all routes in one file, but declare nested route in component having those routes.
Here is Basic Example, You need to add two routes inside Guide Component and to make it relative use match.path.
import React from "react";
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/guide">Guide</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/guide" component={Guide} />
</Switch>
</div>
</Router>
);
}
function Guide({ match }) {
return (
<div>
<h2>Guide</h2>
<ul>
<li>
<Link to={`${match.url}`}>guide</Link>
</li>
<li>
<Link to={`${match.url}/detail`}>Guide Detail</Link>
</li>
</ul>
<Route path={`${match.path}/detail`}
component={GuidePage} />
<Route
exact
path={match.path}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
);
}
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
function GuidePage() {
return (
<div>
<h2>GuidePage</h2>
</div>
);
}
export default BasicExample;
Hope that helps!!!
I have set up a router with animating transitions. Is it possible to trigger transitions on child routes only rather than transitioning the whole page when the user moves from /topics/rendering to /topics/components. Live example: https://codesandbox.io/s/r0PvB30wk
import React from 'react'
import { render } from 'react-dom'
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom'
import { CSSTransitionGroup } from 'react-transition-group'
import About from './components/About'
import Home from './components/Home'
import Topics from './components/Topics'
import './styles.css'
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
);
const Topics = ({ match }) => (
<div className="page">
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic} />
<Route
exact
path={match.url}
render={() => <h3>Please select a topic.</h3>}
/>
</div>
);
export default Topics;
const BasicExample = () => (
<Router>
<Route render={({ location, history, match }) => (
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr />
<CSSTransitionGroup
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
transitionName="fade"
>
<Switch key={location.key} location={location}>
<Route exact path="/" component={Home} location={location} key={location.key} />
<Route path="/about" component={About} location={location} key={location.key} />
<Route path="/topics" component={Topics} location={location} key={location.key} />
</Switch>
</CSSTransitionGroup>
</div>
)}/>
</Router>
)
render(<BasicExample />, document.body)
The only way I could achieve the result was to detect if I was changing from parent to parent or child to child route and turn off the transition based on that.
import React, { Component } from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import { CSSTransitionGroup } from 'react-transition-group';
import About from './components/About';
import Home from './components/Home';
import Topics from './components/Topics';
import './styles.css';
var currentRoute = ''
const getParentPathname = pathname =>
pathname === '/'
? ''
: (/([a-zA-Z])([^/]*)/).exec(pathname)[0]
class BasicExample extends Component {
render = () =>
<Router>
<Route
render={({ location, history, match }) => {
const nextRoute = getParentPathname(location.pathname)
const isAnimated =
!currentRoute.includes(nextRoute) ||
!nextRoute.includes(currentRoute)
currentRoute = nextRoute
return(
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/topics">Topics</Link>
</li>
<li>
<Link to="/askdjhakshd">Unknown</Link>
</li>
</ul>
<hr />
<CSSTransitionGroup
transitionEnter={isAnimated}
transitionLeave={isAnimated}
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
transitionName="fade"
>
{/* switch will render the 1st route that matches */}
<Switch key={location.key} location={location}>
<Route exact path="/" component={Home} location={location} key={location.key}/>
<Route path="/about" component={About} location={location} key={location.key}/>
<Route path="/topics" component={Topics} location={location} key={location.key}/>
<Route render={props => <p>Unknown Route</p>}/>
</Switch>
</CSSTransitionGroup>
</div>
)
}
}/>
</Router>
}
render(<BasicExample />, document.body)
I headed the same problem, so I wrote the module solving this.
https://github.com/melounek/switch-css-transition-group
This SwitchCSSTransitionGroup component is detecting if routes inside are really switching (based on react-router.matchPath) and then changing the Switch key approprietly.
So you can update this code-snippet and it should work:
...
<SwitchCSSTransitionGroup
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
transitionName="fade"
location={location}>
<Route exact path="/" component={Home} location={location} key={location.key} />
<Route path="/about" component={About} location={location} key={location.key} />
<Route path="/topics" component={Topics} location={location} key={location.key} />
</SwitchCSSTransitionGroup>
...
I am new to routing and have been trying around to see what I can do with it.
I want to be able to pass params to a nested route/component. I can pass params to the first component SurveyList. But in the Survey component the params remain undefined.
Is there a way to do this?
routes:
<Switch>
<Route path="/" exact component={Home} />
<Route path="/aboutus/:username" component={AboutUs} />
<Route path="/survey/" component={SurveyList} >
<Route path="/page/:id/" component={Survey} />
</Route>
<Route component={NotFound} />
</Switch>
survey-list
eachSurvey(newText, i){
return(
<Survey key={i} index={i}>
{newText.title}
{newText.desc}
</Survey>);
}
renderList() {
return (
<li>
{this.props.surveys.map(this.eachSurvey)}
</li>
);
}
render() {
return (
<div id="newSurveyButton">
<RaisedButton containerElement={<Link to="survey/page/1"/>} label="Add new Survey" onClick={() => this.props.addSurvey("Titel Survey", "Survey beschrijving")}></RaisedButton>
<ul>
{this.renderList()}
</ul>
</div>
);
}
Survey component render:
<div className="surveyContainer">
<p>{this.props.match.params.id}</p>
<div className="surveyTitle">{this.props.children[0]}</div>
<div className="surveyDesc">{this.props.children[1]}</div>
<RaisedButton label="Add new Page" onClick={() => this.props.addPage("title Page", "Page desc")}></RaisedButton>
<button onClick={this.edit} className="button-primary">Edit</button>
<RaisedButton label="Show Page" onClick={() => this.selectPage(0)} className="showPage"></RaisedButton>
{this.renderPage()
In react-router v2, we can do
// inside of routes.js
export default (
<Route path="/" component={App}>
<IndexRoute component={PostsIndex} />
<Route path="/posts/new" component={PostsNew} />
<Route path="/posts/:id" component={PostsShow} />
</Route>
);
and then show the proper child inside of the App container:
// inside app.js
{this.props.children}
but in react-router v4, {this.props.children} doesn't work any more. Is it done another way?
V4 is a major update and is a complete re-write of <=V3. You shouldn't expect to upgrade to V4 and have everything work still. I recommend checking out the documentation examples so you can see how things work. Here's a basic example which demonstrates nested routes like you have.
import React from 'react'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
const BasicExample = () => (
<Router>
<div>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>
<hr/>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/topics" component={Topics}/>
</div>
</Router>
)
const Home = () => (
<div>
<h2>Home</h2>
</div>
)
const About = () => (
<div>
<h2>About</h2>
</div>
)
const Topics = ({ match }) => (
<div>
<h2>Topics</h2>
<ul>
<li>
<Link to={`${match.url}/rendering`}>
Rendering with React
</Link>
</li>
<li>
<Link to={`${match.url}/components`}>
Components
</Link>
</li>
<li>
<Link to={`${match.url}/props-v-state`}>
Props v. State
</Link>
</li>
</ul>
<Route path={`${match.url}/:topicId`} component={Topic}/>
<Route exact path={match.url} render={() => (
<h3>Please select a topic.</h3>
)}/>
</div>
)
const Topic = ({ match }) => (
<div>
<h3>{match.params.topicId}</h3>
</div>
)
export default BasicExample
I had the same problem and it took a few hours until i found the solution
const PageNavWithChildrenComponentInsideLayout = ({ match }) => {
return <div>
<ul>
<li>
<NavLink className="nav-link" to={"/consultant/childOne"} activeClassName={`${match.url}/childOne` ? "active": ""}>
</NavLink>
<NavLink className="nav-link" to={"/consultant/childTwo"} activeClassName={`${match.url}/childTwo` ? "active": ""}>
</NavLink>
<NavLink className="nav-link" to={"/consultant/childThree"} activeClassName={`${match.url}/childThree` ? "active": ""}>
</NavLink>
</li>
</ul>
{/**
Layout is Wrapper component corresponds parent v2,v3
**/}
<Layout>
{/**corresponds {this.props.children}**/}
<Route exact path={`${match.url}/childOne`} component={ChildOne}/>
<Route exact path={`${match.url}/childTwo`} component={ChildTwo}/>
<Route exact path={`${match.url}/childThree`} component={ChildThree}/>
</Layout>
</div>;
};
export default PageNavWithChildrenComponentInsideLayout
{/**-------------Routes.js--------------*/}
export default routes=()=>{
<Switch>
<Route path="/PageNavWithChildrenComponentInsideLayout" name="Parent" component={PageNavWithChildrenComponentInside}>
<Route path="/PageNavWithChildrenComponentInsideLayout/childOne" name="ChildOne" component={ChildOne} />
<Route path="/PageNavWithChildrenComponentInsideLayout/childTwo" name="ChildTwo" component={ChildTwo} />
<Route path="/PageNavWithChildrenComponentInsideLayout/childThree" name="ChildThree" component={ChildThree} />
</Route>
</Switch>
}