In my react app, I have set up routes like this
class App extends Component {
render() {
return (
<div className="app">
<Header />
<Route exact path="/" component={PostList} />
<Route exact path="/:category" component={PostList} />
<Route exact path="/:category/:postid" component={PostDetails} />
</div>
);
}
}
/ and foo are rendering the PostList component just fine. But when I try to reach the PostDetails component with for instance /foo/bar, it does not get hit.
I tried to play around with the order of the route definitions as well as with the exact prop, but no luck. Not getting any errors, the inspector in devtools just does not show any output where the component should be at.
What am I missing here? I am using react-router-dom#4.2.2.
If you want only one of the routes to show, you should use a Switch.
class App extends Component {
render() {
return (
<div className="app">
<Header />
<Switch>
<Route exact path="/" component={PostList} />
<Route exact path="/:category" component={PostList} />
<Route exact path="/:category/:postid" component={PostDetails} />
</Switch>
</div>
);
}
}
I found the solution. It was simply a typo in the export of the component like this
export { defaut as PostDetails } from './post-details/PostDetails'
missing the l in default.
Strangely enough, I had no errors during transpiling. Sorry people and thanks for your efforts!
Related
I'm currently struggling using React and its library react-router-dom.
To simplify:
I've this in my App component:
const App = () => {
return (
<Router>
<Layout>
<Switch>
// <Other Routes />
<Route path='/product/:id' component={ProductScreen} />
// <Other Routes />
</Switch>
</Layout>
</Router>
)
}
The <ProductScreen /> (single product view) is wrapped like this:
The <ProductNav /> component embeds two links from react-router-dom. It also includes the required logic to reach previous or next product. Like so for instance:
<Link
className='prev'
to={`/product/${currentIndex - 1 < 0 ? ids[lastIndex] : ids[currentIndex - 1]}`}
>
Previous
</Link>
It's working but I'm not satisfied with that approach because the <ProductScreen /> unmounts each time I click 'previous' or 'next' and this leads to some unaesthetic things on the page. I would like to prevent it from unmounting in order to have this instead:
I tried many things, read the doc but I'm quite stuck right now. If anyone has any idea of how to achieve that I would be glad to read it.
You can use Route nested Route as following:
<Header />
<Main>
<Route path="/products" component={Product> />
</Main>
<Footer />
on page Product
const {url} = useRouteMatch();
render() {
<>
<Navbar />
<Route path=`${url}/:id` component={ProductDetail} />
</>
}
In my React Application I need to reload the component when it comes to the path path="/". I know react-router helps us reload easily the current component but I really need this in my application for some styling purpose. In my application I have two paths:
<Route path="/" component={newRoute}/>
and <Route path="/gallery" component={GalleryImages}/>. So, whenever I move from GalleryImages to newRoute I need to reload the newRoute components otherwise the styles are not working. What is the way around here? Here's myApp.js now:
const newRoute = () => {
return (
<div id="colorlib-page">
<div id="container-wrap">
<div id="colorlib-main">
<Introduction/>
<About/>
<Projects/>
<Timeline/>
<Blog/>
</div>
</div>
</div>
)
}
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Sidebar/>
<Switch>
<Route path="/" component={newRoute} exact/>
<Route path="/gallery" component={GalleryImages} exact/>
<Route component={Error}/>
</Switch>
</div>
</BrowserRouter>
);
}
}
export default App;
Try to use class component instead of functional component
In React, I have code like this:
<Router basename='/app'>
<main>
<Menu active={menu} close={this.closeMenu} />
<Overlay active={menu} onClick={this.closeMenu} />
<AppBar handleMenuIcon={this.handleMenuIcon} title='Test' />
<Route path='/customers/:id' component={Customers} />
<Route path='/products/:id' component={Products} />
</main>
</Router>
Every time /customers/:id or /products/:id is accessed, I want to log the access by making an ajax call to a backend service. The fields I will be logging include the referrer URL, the current URL, and a randomly generated session ID (random base 64 integer) What's the best way to do that when I am using the Router component from react-router version 1.0.0.
This has been answered with this question https://stackoverflow.com/a/44410281/5746996
But in essense:
#withRouter
class App extends React.Component {
static propTypes = {
location: React.PropTypes.object.isRequired
}
// ...
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
this.onRouteChanged();
}
}
onRouteChanged() {
console.log("ROUTE CHANGED");
}
// ...
render(){
return <Switch>
<Route path="/" exact component={HomePage} />
<Route path="/checkout" component={CheckoutPage} />
<Route path="/success" component={SuccessPage} />
// ...
<Route component={NotFound} />
</Switch>
}
}
Use the location property in the props property when you have added the react-router. Test to see if it has changed with each update - if it has, you can send it.
In the application the navigation appears single in all the pages except the home which is '/'.
How do I prevent the navigation from appearing twice in the home. Here is a screenshot and the code for the react-router.
Screen Shot OF Double Menu In React-Router:
Here is the code:
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Navigator />
<Switch>
<Route path='/'exact strict component ={HomeIndex} />
<Route path='/Pricing' exact component ={Pricing} />
<Route component={Error404}/>
</Switch>
</div>
</BrowserRouter>
);
}
}
Once check your HomeIndex component, may be you are using <Navigator /> again inside HomeIndex component.
I'm trying to do layouts with react-router.
When my user hits / I want to render some layout. When my user hits /login, or /sign_up I want the layout to render, with the relevant component for /login or /sign_up rendered.
Currently, my App.js looks like this
return (
<div className={className}>
<Route path="/" component={Auth} />
<ModalContainer />
</div>
);
My Auth.js looks like this
return (
<AuthFrame footerText={footerText} footerClick={footerClick}>
<Route path="/login" component={LoginContainer} />
<Route path="/sign_up" component={SignUpContainer} />
</AuthFrame>
);
So AuthFrame will get rendered when I hit /, and then react router looks for login or sign_up to render the other containers.
However, when I hit /, only the AuthFrame will render.
I would like for / to be treated as /login.
How do I achieve this?
The Switch component is useful in these cases:
return (
<AuthFrame footerText={footerText} footerClick={footerClick}>
<Switch>
<Route path="/login" component={LoginContainer} />
<Route path="/sign_up" component={SignUpContainer} />
{/* Default route in case none within `Switch` were matched so far */}
<Route component={LoginContainer} />
</Switch>
</AuthFrame>
);
see: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/Switch.md
I think you're forced to introduce a prop/state which indicates the status of your viewer. This means is he signed in or just a guest of your website.
Your router can't obviously render /login if you you hit / but the router allows you to redirect to another page:
class AuthContainer extends React.Component {
defaultProps = {
loggedIn: false
}
render() {
return <div>
<Route path="/login" component={LoginContainer}/>
<Route path="/sign_up" component={SignUpContainer}/>
</div>
}
}
class PublicHomePage extends React.Component {
render() {
return <div>
<Route path="/settings" component={SettingsComponent}/>
<Route path="/profile" component={ProfileComponent}/>
<Route path="/and_so_on" component={AndSoOnComponent}/>
</div>
}
}
class App
extends React.Component {
defaultProps = {
loggedIn: false
}
render() {
const {loggedIn} = this.props;
if (loggedIn) {
return <PublicHomePage/>
}
return <Route exact path="/" render={() => (
<Redirect to="/login"/>
)}/>
}
}
I hope this code works for you. It isn't quite perfect but it should give you an idea how you could solve your problem.
In your case I would probably manipulate a bit with Routes in react-router. This code in AuthFrame should do the trick:
return (
<AuthFrame footerText={footerText} footerClick={footerClick}>
{["/", "/login"].map((path, ind) =>
<Route exact key={ind} path={path} component={LoginContainer} />
)}
<Route exact path="/sign_up" component={SignUpContainer} />
</AuthFrame>);
Note the usage of exact on the routes, this is to prevent matching login component on /sign_up since it will also match / and prevent rendering both login and signup when accessing the root path (/).