using "react-router": "^3.0.2",
When I do a page reload I need it to go to the default view, which it is currently doing. However, the actual route that is in the history is still the same as the one from where I did the refresh at. So that component is remounting when it shouldn't be.
routing history
export const browserHistory = useRouterHistory(useBeforeUnload(createHistory))()
routes
<Router history={browserHistory}>
<Route path='/' name='Auth' component={Auth}>
<IndexRoute
component={Dashboard}
onEnter={(nextState, replace) => replace('/login')} />
<Route path='dashboard' name='Dashboard' component={Dashboard} />
<Route path='resources' name='Resources' component={Resources} />
<Route path='users' name='Users' component={UsersContainer} />
<Route path='user/:params' name='User' component={UserContainer} />
</Route>
<Route path='/' name='NoAuth' component={NoAuth}>
<Route path='login' name='Login Page' component={Login} />
</Route>
</Router>
This is how I check to see if the user still has a valid session token, and how I reroute to the dashboard. Not sure if I am doing this the best way.
const _checkAuth = () => {
if (profile) {
const res = JSON.parse(profile)
store.dispatch({ type: types.LOGIN_IDENTITY_SUCCESS, res })
console.log(browserHistory.getCurrentLocation().pathname)
router.replace('/dashboard')
}
}
_checkAuth()
if you want to push onto a new route with react-router you can use the .push method to push another route onto the stack, this won't remove the first route in the history if that's what you are looking for, but it will correctly push the new route into react-router
const _checkAuth = () => {
if (profile) {
const res = JSON.parse(profile)
store.dispatch({ type: types.LOGIN_IDENTITY_SUCCESS, res })
console.log(browserHistory.getCurrentLocation().pathname)
browserHistory.push('/dashboard');
}
}
_checkAuth()
Just replace router.replace('/dashboard') with browserHistory.push('/dashboard')
Related
I have a use case where i want to redirect from '/' route to /login whenever someone hits the '/' route. For more clarity i have an app that points to 'app.web.com/login' as the login page. When someone tries to access 'app.web.com' it should redirect to 'app.web.com/login'. I am using react router version 6 and this is what i have tried.
<Routes>
<Route path='/'>
<Navigate to="/auth/login" />
</Route>
<Route path='auth' element={<AuthView />}>
<Route path='login' element={<LoginView />} />
</Route>
<Route path='*' element={<NotFoundView />} />
</Routes>
But it does not have the desired effect. I am pretty much just picking react up so i am sure there is an easy way to do this.
What you could do is make a small component which is rendered on the '/' route which redirects you to the login page.
You could use the useHistory hook for that.
Below is an example of how a component like that looks like.
import React, { useEffect } from 'react';
import { useHistory } from 'react-router-dom';
export const RedirectToLogin: React.FC = () => {
const history = useHistory();
useEffect(() => {
history.push('/auth/login');
});
return null;
};
Your router component would look like:
<Routes>
<Route path='/' element={<RedirectToLogin />} />
<Route path='auth' element={<AuthView />}>
<Route path='login' element={<LoginView />} />
</Route>
<Route path='*' element={<NotFoundView />} />
</Routes
If I understand it correctly then you want to redirect the user to login page if the user is not logged in.
So what you can do is, Instead of trying to do it using route, you can do it from the component which gets rendered when the user goes to /.
You can check in the useEffect hook that if the user exists then go to / else go to /login.
Use the example from below:
useEffect(() => {
if(!user) {
navigate('/')
}
}, [user])
I have been assigned a task where I must put a route with the following url: /items?search= to load SearchBarScreen component.
I have this code and I am using react-router-dom package:
export const AppRouter = () => {
return (
<Router>
<Switch>
<Route exact path="/items?search=" component={SearchBarScreen} />
<Route exact path="/product/:id" component={ProductDetailScreen} />
<Route path="/" component={HomeScreen} />
<Route component={NotFoundScreen} />
</Switch>
</Router>
);
I can't load my SearchBarScreen component with the url:
http://localhost:3000/items?search=XDDD
the route HomeScreen (/) is loaded in this case :(
what am I doing wrong?
You should feed the URI without the query string to the Route component. So if you want to render your SearchBarScreen at this URL http://localhost:3000/items?search=, you should do this:
<Route exact path="/items" component={SearchBarScreen} />
And then access the query string inside SearchBarScreen like so:
const SearchBarScreen = ({ match, location }) => {
console.log(location.search);
return <div>Search results</div>;
};
Another way is to drop the exact prop.
My recommended solution is the former. Here is a Sandbox: https://codesandbox.io/s/elated-http-lkqfj?file=/src/App.js
The exact param is used when you have multiple paths that have similar names:
for exmplae in your code when you go to //localhost:3000/items?search=XDDD the router will go through all of our defined routes and return the FIRST match it finds.And this is the first thing it finds //localhost:3000/ And executes the HomeScreen component.
The exact param disables the partial matching for a route and makes sure that it only returns the route if the path is an EXACT match to the current url.
So in this case,you should add exact to / route:
<Router>
<Switch>
<Route path="/items?search=" component={SearchBarScreen} />
<Route path="/product/:id" component={ProductDetailScreen} />
<Route exact path="/" component={HomeScreen} />
<Route component={NotFoundScreen} />
</Switch>
</Router>
You can do something like this
You can use this custom hook
useLocation hook is imported from react-router-dom
useQuery() {
return new URLSearchParams(useLocation().search);
}
Then in component
const query = useQuery();
Docs Query param example
I have many routes
<Route exact path="/" component={Test} />
<Route exact path="/1" component={Test1} />
<Route exact path="/2" component={Test2} />
In every component i use useLocation to get the data from route. It exists a possibility to pass in Route a parameter and to access that parameter with useLocation, in every component?
Here is the example:
<Route exact path="/" parameter='this is route nr 1' component={Test} />
<Route exact path="2/" parameter='this is route nr 2' component={Test2} />
Which is the solution to do what i want to achieve?
For query params you don't need to do anything extra in <Route />. You just need to get those query params in component and parse it
To access param1 from url
/?param1=hello
import { useLocation } from 'react-router-dom';
const Test = () => {
const queryParams = new URLSearchParams(useLocation().search);
return (
<div>Test {queryParams.get('param1')}</div>
);
}
And if you want path params like
/1 // 1 from this route
In routes and you don't need to create multiple routes just to get 1,2 etc
<Route exact path="/:id" component={Test} />
In component
import { useParams } from 'react-router-dom';
const Test = () => {
let { id } = useParams();
return (
<div>Test ID: {id}</div>
);
}
It seems from your question that you search for a way to pass data to routes only at the router declaration. therefore you can use regular props instead of location data extract -
<Route exact path="/" render={()=><Test parameter={'this is route nr 1'} />} />
You can either pass props to the component directly using render:
<Route
exact
path="/"
render={props => <MyComponent {...props} foo="hello world" bar={false} /> }
/>
or you can use query params:
<Route
exact
path={`/user?id=${user_id}`}
component={MyComponent}
/>
and then in MyComponent you can access props.match.params.id
React-router docs are a great start
I am following a tutorial which is a bit old but I am using "react-router": "^5.0.0" I think it now do not support onEnter and OnChange. So what should i use instead while keeping same functionality.
export const globalOnChange = (prevState, nextState) => {
globalOnEnter(nextState);
};
export const globalOnEnter = (nextState) => {
const lastRoute = nextState.routes[nextState.routes.length - 1];
Session.set('currentPagePrivacy', lastRoute.privacy);
console.log('lastRoute',lastRoute);
};
export const routes = (
<Router history = {browserHistory1}>
<Route onEnter={globalOnEnter} onChange={globalOnChange}>
<Switch>
<Route exact path = "/" component={Login} privacy="unauth"/>
<Route exact path = "/signup" component={Signup} privacy="unauth"/>
<Route exact path = "/dashboard" component={Dashboard} privacy="auth"/>
<Route exact path = "/test" component={Test} privacy="auth" onEnter={onEntertESTPage}/>
<Route component={NotFound}/>
</Switch>
</Route>
</Router>
);
onEnter no longer exists on react-router-4. With v4, you should use the lifecycle methods of the component rendered by a . Instead of onEnter, you would use componentDidMount.
https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/migrating.md#on-properties
So I would also recommend setting/checking the privacy rules in the component itself and not the router.
We've localized our app and now I need to include the lang in all routes, I've come across code that would do what I want but have trouble doing the same in react-router v4
Here is the code I'm referencing
How to set and handle language in react-router from?
Here is the sample code I'm working with to get it functional before integrating it in our app:
// add lang to url if it's not present
function langRedirect(props) {
console.log({ props });
const defaultLang = 'en';
const redirectPath = `/${defaultLang}${props.history.location.pathname}`;
console.log(redirectPath);
props.history.replace({ pathname: redirectPath, });
}
....
<Switch>
<Route path="/:lang/" render={() => <h1>testing... does nothing</h1>}>
<Route path="/:lang/test" render={() => <h2>Test</h2>} />
<Route path="/:lang/test2" render={() => <h2>Test2</h2>} />
</Route>
<Route path="*" render={langRedirect} />
</Switch>
What happens here is if I go to a route like /test the switch will still catch the /:lang/ route even if there is no / at the end which prevents going to the route with langRedirect. Seems like a different behaviour in v4.
Well, after spending hours on this I happened to figure it out right after posting the question...
I had to add a * to the route like so <Route exact path="/:lang/*" render={() => <h1>Test</h1>}>
Here is the working code:
// add lang to url if it's not present
function langRedirect(props) {
console.log({ props });
const defaultLang = 'en';
const redirectPath = `/${defaultLang}${props.history.location.pathname}`;
console.log(redirectPath);
props.history.replace({
pathname: redirectPath,
});
}
...
const TestingRoutes = () => {
return (
<Switch>
<Route exact path="/:lang/*" render={() => <h1>Test</h1>}>
<Route path="/:lang/test" render={() => <h2>Test</h2>} />
<Route path="/:lang/test2" render={() => <h2>Test2</h2>} />
</Route>
<Route path="*" render={langRedirect} />
</Switch>
);
};