I have a basic routing SPA working using react-router-dom v4 and I would like to get the current route (path name) for use in my header (outer context of the app - not sure if that's accurate nomenclature). I want to have a button in my app bar which will do something depending on the route currently in use.
index.js
ReactDOM.render((
<MuiThemeProvider>
<div>
<Router history={history}>
<div>
<Header />
<MainView />
</div>
</Router>
</div>
</MuiThemeProvider>
), document.getElementById('app'));
header.js
class Header extends React.Component {
constructor(props){
super(props);
this.state = {
open: false
};
}
toggleDrawer(){
this.setState({open: !this.state.open}, ()=> {console.log(this.state)});
}
render() {
return (
<div>
<AppBar
iconClassNameRight="muidocs-icon-navigation-expand-more"
onLeftIconButtonTouchTap={()=>{this.toggleDrawer()}}
iconElementRight={<FlatButton label="Create New"/>}
/>
...
In the header.js I want access to the route's pathname to call a certain function from the <FlatButton /> on the right of the appbar. I've tried {this.props.location.pathname} as per the v4 docs but only got errors. TBH I was probably using it wrong though.
That prop is only provided to components rendered as the child of a Route. If you want it somewhere else (like in your Header), you can use the withRouter helper method to inject the props into your component:
// Header.js
import { withRouter } from 'react-router';
// private header class
class Header extends React.Component {
render() {
// you can access this.props.location here
}
}
// wrap Header class in a new class that will render the
// Header class with the current location
// export this class so other classes will render this
// wrapped component
export default withRouter(Header);
// index.js
// ....
ReactDOM.render((
<MuiThemeProvider>
<div>
<Router history={history}>
<div>
<Header />
<MainView />
</div>
</Router>
</div>
</MuiThemeProvider>
), document.getElementById('app'));
You should use react-router-dom if you are not using it (it's the default react-router package for the web now).
import { BrowserRouter, Route, Link } from 'react-router-dom';
ReactDOM.render((
<MuiThemeProvider>
<div>
<BrowserRouter>
<div>
<Route component={Header} />
<Route exact path="/" component={MainView} />
</div>
</BrowserRouter>
</div>
</MuiThemeProvider>
), document.getElementById('app'));
and then from the header.js try using
this.props.location.pathname
Related
I am just starting to learn React from this tutorial. I created components and imported them on my App.js.
However, I noticed that the components are not showing up when I run npm start (i.e. "Welcome to Create Todo Component!!" does not appear). I am also not receiving any error messages. Am I doing something wrongly?
Thanks in advance!
App.js
...
import CreateTodo from "./components/create-todo.component";
import EditTodo from "./components/edit-todo.component";
import TodosList from "./components/todos-list.component";
class App extends Component {
render() {
return (
<Router>
<div className="container">
...
<Route path="/" exact component={TodosList} />
<Route path="/edit/:id" component={EditTodo} />
<Route path="/create" component={CreateTodo} />
...
create-todo.component.js
import React, { Component } from 'react';
export default class CreateTodo extends Component {
render() {
return (
<div>
<p>Welcome to Create Todo Component!!</p>
</div>
)
}
}
You need to actually render your app to the DOM in order for it to display on screen, do you do that? Something like this:
ReactDOM.render(
<App/>,
document.getElementById('root')
);
In this case, there is an App component which has a Header component which renders one header if the user is logged in and one if not. There is also an Access component which renders either a Landing component if user is not logged in or Dashboard if the user is logged in. The user has access to all routes if logged in. How do I render components using react-router-dom if the user is on the Dashboard component? Currently, LeftNav should always be in view while the components in the main-content className toggle based on the route. Currently only the LeftNav and MainContent components work on "/", if navigated to /test or /test/new neither the LeftNavorTestComponentrender, however theHeadercomponent is still rendering correctly. What am I doing wrong here or how is this toggling betweenmain-content` components achieved?
import { BrowserRouter, Route } from "react-router-dom";
import Header from "./Header";
import Access from "./Access";
class App extends Component {
render() {
return (
<div>
<BrowserRouter>
<div>
<Header />
<Route exact path="/" component={Access} />
</div>
</BrowserRouter>
</div>
);
}
};
export default App;
////////////////////////////////
import Landing from "./Landing";
import Dashboard from "./Dashboard";
class Access extends Component {
renderContent() {
switch (this.props.auth) {
case null:
return;
case false:
return (
<Landing />
);
default:
return (
<Dashboard />
);
}
}
render() {
return (
<div>
{this.renderContent()}
</div>
);
}
}
export default Access;
////////////////////////////////
import { Switch, Route } from "react-router-dom";
import LeftNav from "./dashboard/LeftNav";
import MainContent from "./dashboard/MainContent";
import TestContent from "./dashboard/TestContent";
import TestContentNew from "./dashboard/TestContentNew";
class Dashboard extends Component {
render() {
return (
<div>
<div className="dashboard-wrapper" style={dashboardWrapper}>
<LeftNav />
<div className="main-content">
<Switch>
<Route path="/" component={MainContent} />
<Route path="/test" component={TestContent} />
<Route path="/test/new" component={TestContentNew} />
</Switch>
</div>
</div>
</div>
);
}
};
export default Dashboard;
Issue
The main Route in your application only ever matches and renders a route when it exactly matches "/", so when you navigate to another path it ceases to match.
Solution
I don't see where you pass auth as a prop to Access, but since it handles authentication and renders your actual routes you can simply just render it instead of a Route in App. It will always be rendered by the router and display either the landing page or the dashboard.
import { BrowserRouter, Route } from "react-router-dom";
import Header from "./Header";
import Access from "./Access";
class App extends Component {
render() {
return (
<div>
<BrowserRouter>
<div>
<Header />
<Access />
</div>
</BrowserRouter>
</div>
);
}
};
Hello I'm having a problem with setting 'react-router-modal' parentPath for the last used component
ModalRoute and ModalContainer are a part of
react-router-modal
App.js
class App extends Component {
render() {
return (
<main>
<Navbar />
<BrowserRouter>
<div>
<Switch>
<Route path="/main" component={ContentDefault} />
<Route path="/search" component={SearchScreen} />
<ModalRoute
path="/register"
parentPath="/"
component={RegisterScreen}
/>
<Route path="/contact" component={ContentDefault} />
<Route component={ContentDefault} />
</Switch>
<ModalContainer />
</div>
</BrowserRouter>
<Footer />
</main>
);
}
}
export default App;
SearchScreen.jsx
import React, { Component } from "react";
import { withRouter } from "react-router-dom";
class SearchScreen extends Component {
render() {
return (
<main>
<h1>SearchScreen</h1>
</main>
);
}
}
export default withRouter(SearchScreen);
For Example i'm on mainScreen then i move to the SearchScreen then i open modal from navbar. I need my modal to go back to the SearchScreen
I found couple of solutions which may help you.
You can try with this:
Create state prevPath
Add componentWillReceiveProps
Provide prevPath state to the parentPath with condition if prevPath is empty redirect me on route '/'
class App extends Component {
state = {
prevPath: ''
}
componentWillReceiveProps(nextProps) {
if (nextProps.location !== this.props.location) {
this.setState({ prevPath: this.props.location })
}
}
<ModalRoute
path="/register"
parentPath={this.state.prevPath || '/'}
component={RegisterScreen}
/>
This is one of the solutions we can try later another one if this doesn't help.
I'm new to React and trying to follow a tutorial on how to set up the router. However when I run the app, the component does not render, and the HTML just says react-empty.
index.js:
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
App.js:
const App = () => (
<div>
<Main />
</div>
)
export default App;
Main.js:
const Main = () => (
<div>
<main>
<h1>MAIN</h1>
<Route exact path="/" component={Home}/>
</main>
</div>
)
export default Main;
Home.js:
class Home extends Component {
constructor() {
super()
console.log('home component');
}
render() {
return (
<div>
<h1 className="wat">waaaat</h1>
</div>
)
}
}
export default Home;
Also, I can see the Route in the React plugin for chrome like so: http://imgur.com/a/LXuwC
EDIT:
It works if i put:
<Switch>
<Route path="/" component={Home}/>
</Switch>
directly in App.js instead of the Main element.
I'm failing at passing a property from a <Route />
Here is some code :
./app.jsx (main app)
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, IndexRoute } from 'react-router'
import App from './components/app'
import Home from './components/home'
import About from './components/about'
render((
<Router>
<Route path="/" component={App}>
<IndexRoute component={Home} title="Home" />
<Route path="about" component={About} title="About" />
</Route>
</Router>
), document.getElementById('app'))
./components/app.jsx
import React from 'react';
import Header from './template/header'
class App extends React.Component {
render() {
return (
<div>
<Header title={this.props.title} />
{this.props.children}
</div>
)
}
}
export default App
./components/template/header.jsx
import React from 'react'
class Header extends React.Component {
render() {
return (
<span>{this.props.title}</span>
)
}
}
export default Header
When I click on my home route* I want my Header component to display Home.
When I click on my about route I want my Header component to display About.
At this point, my Header components displays nothing. this.props.title is undefined in my App component.
Looks like you can't pass an attribute from a <Route />
Is there a way to achieve this?
Or is there another way? For instance, can you get something from the children element (this.props.children.title or something like that) ?
It looks like the route injects a routes property with a list of the matching routes. The last route in the list has the props you specify. See http://codepen.io/anon/pen/obZzBa?editors=001
const routes = this.props.routes;
const lastRoute = routes[routes.length - 1];
const title = lastRoute.title;
I'd hesitate a little to use this, since routes is not documented in the Injected Props, so I don't know how reliable it is across version updates. A simpler option, though not as legible, would be to use this.props.location.pathname and maintain a lookup table for titles.
The best and most flexible option is probably the boilerplate-heavy one, where you define the template and then reuse it across components:
class Template extends React.Component {
render() {
return (
<div>
<Header title={this.props.title} />
{this.props.children}
</div>
)
}
}
class About extends React.Component {
render() {
return (
<Template title="About">
Some Content
</div>
)
}
}