I have simple movie app with a home page and a watchlist page.
This is how I would like to structure it:
Home
/movie/id
Watchlist
watchlist/movie/id
I would like to access the movie/id from both the home page and the watchlist. Right now I can access it but the problem is when I open a movie when I'm on watchlist page it goes back to home and opens it from there, instead of staying on watchlist and opening it from there. I'm using React-Router v5.2. What should I write differently in the route? I tried /watchlist/movie/:id but then it didn't render the movie at all, only from Home.
function App() {
return (
<div className='App' style={{ overflowX: 'hidden' }}>
<GlobalStyles />
<Switch>
<Route exact path={['/movie/:id', '/']}>
<Home />
</Route>
<Route exact path={['/movie/:id', '/watchlist']}>
<Watchlist />
</Route>
</Switch>
</div>
);
}
export default App;
And that's the link for the movie page:
<Link to={`/movie/${id} `}>
</Link>
The issue is that the react router tries to match the first url and it is inside switch that will tell to render only one component , you need to remove switch , also donot forget to use BrowserRouter wrapper , as i donot see it in code
function App() {
return (
<div className='App' style={{ overflowX: 'hidden' }}>
<GlobalStyles />
<Route exact path={['/movie/:id', '/']}>
<Home />
</Route>
<Route exact path={['/movie/:id', '/watchlist']}>
<Watchlist />
</Route>
</div>
);
}
I rearranged my code the following way which fixed it. According to docs the more specific path like: /watchlist/movie/:id should come before the less specific path="/watchtlist".
<Switch>
<Route exact path='/watchlist/movie/:id'>
<MovieDetail pathId={pathId} />
</Route>
<Route path='/watchlist'>
<Watchlist />
</Route>
<Route path='/movie/:id'>
<MovieDetail pathId={pathId} />
</Route>
<Route exact path='/'>
<Home />
</Route>
</Switch>
Related
i have a react app in which i want that if user route start with admin it should have a different navbar
lets take example
normal page
<NormalNavbar/>
<NormalHeader/>
<NormalBody/>
<NormalFooter/>
But if i have the admin route
then i want to have
<AdminNavbar/>
<AdminHeader/>
<AdminBody/>
<AdminFooter/>
The issue is when we wind it inside the Routes then we decide the normal components which are loading i will paste the example below
return (
<div className="App">
<>
<Navbar />
<Routes>
<Route exact path="/" element={<HomePage />} />
<Route exact path="/product/:id" element={<ProductPage />} />
<Route exact path="sarangAdmin/create-product" element={<CreateProduct />} />
<Route exact path="login" element={<Login />} />
<Route exact path="profile" element={<Profile />} />
<Route exact path="register" element={<Register />} />
</Routes>
<Footer />
</>
</div>
);
You can see my current navbar and footer going to be same
you can put elements with conditions like that
{isAdmin? <AdminNavbar> : <NormalNavbar> }
OR
in the navbar component view different menu
See the above answers is good but its not the optimal solution I wanted so I get the solution by looking other git repository here is the repository that shows how you should do it in a perfect way make route component structure and then you can render them conditionally which I wanted in my case the most optimum solution to my question
UPDATE
Guys, you have helped me to solve part of the issue.
The new issue now is that, when I do the login in the App, it appears wrong for me like below:
And it has to appear in the right way what is represented below:
I've looked forward in the code and I think it could be some issue in App.js at the following snippet:
return (
<BrowserRouter>
<Fragment>
<LoadingBar style={{ zIndex: 1000 }} />
<Menu />
<div className='ui main text container' style={{ marginTop: '7em' }}>
<Switch>
<Route
path='/'
exact
render={() => {
return (
<QuestionList
handleTabChange={this.handleTabChange}
activeIndex={this.state.activeIndex}
/>
)
}}
/>
But I haven't figured out what could it be the problem. I've tried to search something here in stackoverflow and I haven't obtained success.
I've modified in codesandbox for the same way is for me now. Please check there and I'd appreciate any help:
https://codesandbox.io/s/compassionate-sammet-iincf
Thanks a lot again.
In App.js you had the following routes defined for when the user is logged in:
<Route
path="/"
exact
render={...}
/>
<Route
path="/add"
render={...}
/>
<Route path="/questions/:question_id" component={QuestionView} />
<Route path="/leaderboard" component={Leaderboard} />
<Route path="/logout" component={Logout} />
<Route path="/404" component={PageNotFound} />
<Route path="/" component={PageNotFound} />`
Notice that there is no "/login" route defined for when a user is logged in. This is why you're getting the PageNotFound error. Also you've defined the "/" route twice, so you'll want to remove the second definition.
I am building a React app that has a static marketing site and a dynamic app. I am using a combination of React Router and hooks to separate the two and ensure proper routing throughout.
To begin with, I want users who are logged in to be taken directly to the app when they hit the root ("/") and to the static/marketing site when not logged in. The main marketing site home page has a nav bar that allows users to access other routes such as "/about", whereas the app has a separate nav bar for app navigation.
The problem is, while the authentication based routing for the root route seems to be working, and I can navigate to other routes specified in my top-level file, the routes that are included within my static/marketing site are not accessible.
Top-level/index.js
const routing = (
<Provider store={store}>
<Router>
<NavWrapper />
{/* <Switch> */}
<Route exact path="/" component={AuthWrapper} />
<Route path="/signup" component={SignUp} />
<Route path="/login" component={Login} />
{/* </Switch> */}
</Router>
</Provider>
)
ReactDOM.render(routing, document.getElementById('root'));
AuthWrapper.js (here useAuth() is a React hook that evaluates global Redux isAuthenticated state)
const AuthWrapper = (props) => {
return useAuth() ? <App /> : <Website />
}
export default AuthWrapper;
website/index.js
export const Website = () => {
return (
<>
{/* <SiteNav /> */}
<Switch>
<Route exact path="/" component={LandingPage} />
<Route path="/about" component={AboutPage} />
<Route path="/how-it-works" component={HowItWorksPage} />
<Route path="/plans" component={PlansPage} />
<Route path="/press" component={PressPage} />
<Route path="/faq" component={FAQPage} />
<Route path="/legal" component={LegalPage} />
<Route path="/for-dieticians" component={DietitiansPage} />
<Route path="/for-trainers" component={PTsPage} />
</Switch>
</>
)
};
In my app, when I enter localhost:3000/ (unauthenticated) I am correctly taken to my home/landing page. However, if I try to use the navigation (or type in any subroutes) to access "/about" for example, I get a blank screen (other than the nav bar). In the React dev tools, the component isn't even rendering.
I think this is the issue:
<Route exact path="/" component={AuthWrapper} />
You want Authwrapper to be shown for about as well, right? But the above only matches "/" exactly.
You should enable the switch statement, but move the AuthWrapper Route to the bottom and then let it have this path: "/:rest*" (maybe "/*" works too, haven't used react-router in a while).
That way, it will use the Route if the first 2 don't match.
I'm working with reactJs and trying to create some nested routes.
Below you can see the routing parts of my files :
main.js :
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('page')
);
App.js :
class App extends Component {
render() {
return (
<div>
<Header />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/signup" component={SignUp} />
<Route path="/contact" component={Contact} />
<ProtectedRoute path="/user/profile" component={Profile} />
<Route component={NotFound} />
</Switch>
<Footer />
</div>
);
}
}
Don't ask me why, but I want to create the following url's :
/signup : SignUp form
/signup/person : SignUp form part 2
/signup/person/:id : SignUp user id informations
I added this in my App.js file and It's works :
<Route exact path="/signup" component={SignUp} />
<Route exact path="/signup/person" component={SignUpPerson} />
<Route path="/signup/person/:id" component={SignUpId} />
But I want to know if it's a good way to create nested routes or it's better to separate the route like this post : https://stackoverflow.com/a/43846223/4023379
Or maybe an other way ?
Thanks
use nested routes if Pages have common logic/components like Header, Footer.
use separate routes if Page doesn't share similar logic. just because of url start with /singup not necessary mean you have to nested your components
I have a problem with my react components.
Basically my interface should be an SPA, built with ReactJS.
During the implementation of the authentication with auth0-js I also implemented some routes.
The layout looks like this:
Whenever I click now on the "Recipes" link, it should redirect to the route "/recipes".
However, when I implement the route with <Route path="/recipes" component={Recipes} /> it only renders what is actually returned in the Recipes component. I know that this is correct from what react does.
Now, I want to keep the navigation bar but only want to exchange the component below, so I want to change what is below the navigation bar like I did in App.js.
How can I achieve this? Is something about the routes, or components not correct?
I do not want to re-render always everything. I also want to keep the style of the whole page. Is there a way to do this?
The whole code can be found here.
I agree with Jyutzio in that you need to move the Navigation component above the child routes to only change to content of the child routes.
In order to have the Navigation bar update with logged in / logged out state you may want to consider implementing redux. I have a project with nearly the exact requirements as yours - a navigation header that is static.
In my header I have import { connect } from 'react-redux';
At the bottom of the component I use connect before exporting:
function mapStateToProps(state) {
return { authenticated: state.auth.authenticated };
}
Header = connect(mapStateToProps)(Header);
export default Header;
Then this allows me to check the "authenticated" piece of state and render accordingly.
renderLogoutButton() {
if(this.props.authenticated) {
return(
<li><a onClick={...}>Logout</a></li>
);
} else {
return(
<li><a onClick={...}>Login</a></li>
);
}
}
You will need to setup a reducer, but there are many resources explaining redux setup.
The router (simplified) I have set up as follows:
import Admin from './index';
...
<BrowserRouter>
<Switch>
<Route exact path="/login" component={Login} />
<Route path="/" component={Admin} />
</Switch>
</BrowserRouter>
index:
import AdminRouter from './admin/admin_router';
...
<div>
<Menu />
<div>
<AdminRouter />
</div>
</div>
admin_router:
<div>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/details" component={AdminDetails} />
<Route component={PageNotFound} />
</Switch>
</div>
If you place your Navigation component above the switch, it will solve your problem.
const Routes = () => (
<Router history={history} component={Home}>
<Route component={Navigation}/>
<Switch>
<Route exact path="/" render={props => <Home auth={auth} {...props} />} />
<Route path="/home" render={props => <Home auth={auth} {...props} />} />
<Route
path="/callback"
render={props => {
handleAuthentication(props);
return <Callback {...props} />;
}}
/>
<Route component={NotFound} />
</Switch>
</Router>
);