I have a component, where i have to call navigate to main page, but navigate is not working, where is my fall? I know that userName is changing but redirect doesn't happening
Index.js
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
App.js
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/settings" element={<Settings />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
)
Login.js
const dispatch = useDispatch();
const user = useSelector((store) => store.user);
let navigate = useNavigate();
const onSubmitForm = (e) => {
e.preventDefault();
dispatch({
type: FETCH_USER,
payload: { login: user.login, password: user.password },
});
}
useEffect(() => {
if(user.userName) {
navigate("/login");
}
}, [user.userName])
I am not sure if it is the case but try changing the order of your paths to this:
return (
<Switch>
<Route path="/login" element={<Login />} />
<Route path="/settings" element={<Settings />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/" element={<Home />} />
</Switch>
)
I had a similar thing before and somehow navigation was always navigating to the Home because path"/" was on top.
Also a small thing, I normally use the Routes with Switch. In my experience above structure should work
Related
how it is possible to remove this routing in a separate component? I tried to do it through the map but it did not work
I want only one route to remain and when you click on a certain link, 'path' changes in it
const Home = ({ code }) => {
return (
<div className="wrapper__flex_main">
<TheNav {...code} />
<Routes>
<Route path='/' element={<Main code={code} />} />
<Route path='/search' element={<TheSearchTrack code={code} />} />
<Route path='/likes' element={<Likes code={code} />} />
<Route path='/artist' element={<Artist code={code} />} />
<Route path="/genre/:id" element={<GenreTemplate code={code} />} />
<Route path="/artist/:id" element={<ArtistPages code={code} />} />
<Route path="/genretrack/:id" element={<GenreTrack code={code} />} />
<Route path="/track/:id" element={<Track code={code} />} />
</Routes>
</div>
)
}
export default Home
const navigate = useNavigate();
...
const loginHandler = () => {
... business logic ...
// if logic true
navigate('navigate-path', { replace: true }); // redirect!!!
};
You can use something like this , this prevent user navigation to other pages
function App() {
return (
<RecoilRoot>
<Router>
<Navbar />
<Routes>
<Route path={"/"} element={<Home />} />
<Route path={`/page/:menu`} element={<MovieMenu />} />
<Route path={`/movie/:id`} element={<Detail />} />
<Route path={`/search/:searchText`} element={<Search />} />
<Route path={"*"} element={<NotFound />} />
</Routes>
</Router>
</RecoilRoot>
);
}
If i process 404 page in the above way, / handle it well, but <NotFound /> not be rendered if any path is entered after /page/fldlfsd;lf; or /search/dsklfskldf. Is there a way?
Paths like "/page/fldlfsd;lf;" and "/search/dsklfskldf" will be matched and rendered by the Routes component. The route param validation needs to occur in the routed component.
Each component can use the useParams hook to access the route param, validate it, and redirect to the NotFound route if param is invalid.
To help with this I suggest creating a discrete route to render NotFound so you can imperatively redirect to it from components and create a redirect route to handle unknown routes.
Example:
function App() {
return (
<RecoilRoot>
<Router>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/page/:menu" element={<MovieMenu />} />
<Route path="/movie/:id" element={<Detail />} />
<Route path="/search/:searchText" element={<Search />} />
<Route path="/404" element={<NotFound />} />
<Route path="*" element={<Navigate to="/404" replace />} />
</Routes>
</Router>
</RecoilRoot>
);
}
...
MovieMenu
const navigate = useNavigate();
const { menu } = useParams();
useEffect(() => {
... logic to validate menu param ...
if (invalidMenu) {
navigate("/404", { replace: true });
}
}, [menu, navigate]);
...
I have a React site with three different routes, and I want it to automatically display the first one, which is called Home, when a user enters the site. Here is the code I have in App.js:
<Router>
<Navigation />
<Switch>
<Route path="/hypstats" exact component={() => <Home />} />
<Route path="/hypstats/auctions" exact component={() => <AuctionViewer />} />
<Route path="/hypstats/bazaar" exact component={() => <BazaarViewer />} />
</Switch>
</Router>
And here is the Navigation component:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import "../App.css"
function Navigation(props) {
return (
<div className="navbar">
<Link className="navlink" to="/hypstats">HypStats</Link>
<Link className="navlink" to="/hypstats/auctions">Auctions</Link>
<Link className="navlink" to="/hypstats/bazaar">Bazaar</Link>
</div>
)
}
export default Navigation;
To make any view as the default view you could include the following into your Navigation
<Route path="/" exact component={() => <Home />} />
Or you could write as below:
<Redirect from="/" to="/hypstats"} />
<Router>
<Navigation />
<Switch>
<Route path="/hypstats" exact component={() => <Home />} />
<Route path="/hypstats/auctions" exact component={() => <AuctionViewer />} />
<Route path="/hypstats/bazaar" exact component={() => <BazaarViewer />} />
**<Route path="/" exact component={() => <Home />} />**
</Switch>
</Router>
We use the basename attribute to tell the basename of the site. So that in the next routes, we would not have to set basename, here /hypstats, manually every time we add a new route. React Router manages it by itself.
<Router basename="/hypstats">
<Navigation />
<Switch>
<Route path="/" exact component={() => <Home />} />
<Route path="/auctions" exact component={() => <AuctionViewer />} />
<Route path="/bazaar" exact component={() => <BazaarViewer />} />
</Switch>
</Router>
Run this somewhere in your App component.
history.push({
pathname: '/hypstats',
});
You are using "react-router-dom" so you can import:
import { useHistory } from "react-router-dom";
And then you can use:
const history = useHistory();
So whenever user enters your react application it will open the '/hypstats'.
You could do this in a useEffect.
I had a web app where you had to be authentified to see the content. First thing you saw entering the website was the Keycloak login page rendered in Login.js, once you were logged in, you had access to Routes.js. Now I have to add public routes to this same application and I'm not sure how to proceed. Here's what I have so far.
Index.js
<Suspense fallback='loading'>
<BrowserRouter>
<PublicRoutes/>
</BrowserRouter>
</Suspense>
PublicRoutes.js
return (
<Switch>
<Route exact path="/" render={() => <Redirect to="/signup"/>}
/>
<Route exact path="/signup" render={() => <SignupPage header={HeaderNav}/>}
/>
<Route exact path="/login" render={() => <Login/>}
/>
</Switch>
);
Login.js
if(this.state.keycloak) {
if(this.state.authenticated) return (
<Routes keycloak={this.state.keycloak}/>
); else return (<div>Unable to authenticate!</div>)
}
return (
<div>Loading, please wait...</div>
);
Routes.js
<Switch>
<Route exact path="/" render={() => <Redirect to="/home"/>}
/>
<Route exact path="/home" render={() => <HomePage header={HeaderNav} sidebar={Sidebar}/>}
/>
<Route exact path="/catalog" render={() => <CatalogPage header={HeaderNav} sidebar={Sidebar}/>}
/>
<Route exact path="/query" render={() => <QueryPage header={HeaderNav} sidebar={Sidebar}/>}
/>
<Route exact path="/workshop" render={() => <WorkshopPage header={HeaderNav} sidebar={Sidebar}/>}
/>
<Route exact path="/dashboard/stats" render={() => <StatsPage header={HeaderNav} sidebar={Sidebar} keycloak={this.props.keycloak}/>}
/>
<Route exact path="/dashboard/keys" render={() => <KeysPage header={HeaderNav} sidebar={Sidebar} keycloak={this.props.keycloak}/>}
/>
<Route exact path="/dashboard/consumption" render={() => <ConsumptionPage header={HeaderNav} sidebar={Sidebar} keycloak={this.props.keycloak}/>}
/>
<Route exact path="/faq" render={() => <HelpPage header={HeaderNav} sidebar={Sidebar}/>}
/>
<Route exact path="/contact_us" render={() => <ContactPage header={HeaderNav} sidebar={Sidebar}/>}
/>
<Redirect from="/login" to="/home"/>
</Switch>
What I'd like is that the Routes.js file takes over the PublicRoutes.js file when the user is authentified. Right now, when the user logs in, he can still only see the public routes content.
Try lifting state up. Maybe Index.js can switch between 2 sets of routers?
You can pass state (Keycloak object) or callbacks (handleLogin) for Login.js if you need to
Example:
render() {
const { keycloak, authenticated } = this.state;
return
<div>
{authenticated ? (
<Secured keycloak={keycloak} />
) : (
<Public handleLogin={this.handleLogin} />
)}
</div>
}
So basically I have a navbar that switches between routes. When the page loads, it goes to /home by default but doesn't actually render the App component it's being given. I have to click on the button that brings you to /home in order to render this.
I'm using react-router-dom with Redux.
Here's my BrowserRouter:
<Provider store = {store}>
<BrowserRouter>
<div>
<Header />
<Route exact path = "/home" component={App}> </Route>
<Switch>
<Route path = "/about" render = {() => <AboutUs />}></Route>
<Route path = "/contact" render = {() => <Contact />}></Route>
<Route path = "/services" render = {() => <Services />}></Route>
</Switch>
</div>
</BrowserRouter>
</Provider>
Any advice?
The default route is / not /home.
You need to setup a redirect.
<Route exact path="/" render={() => (
<Route exact path="/home" component={App} />
)} />
Put your /home route in the Switch with all the other routes:
<Provider store = {store}>
<BrowserRouter>
<div>
<Header />
<Switch>
<Route exact path = "/home" component={App}> </Route>
<Route path = "/about" render = {() => <AboutUs />}></Route>
<Route path = "/contact" render = {() => <Contact />}></Route>
<Route path = "/services" render = {() => <Services />}></Route>
</Switch>
</div>
</BrowserRouter>
</Provider>
You need to put /home inside <Switch>
<Route exact path = "/home" component={App}> </Route>
Means put above line of code inside <Switch>
ex:-
<Switch>
<Route exact path = "/home" component={App}> </Route>
<Route path = "/about" render = {() => <AboutUs />}></Route>
<Route path = "/contact" render = {() => <Contact />}></Route>
<Route path = "/services" render = {() => <Services />}></Route>
</Switch>