I need a dynamic routing in my Reac app that use reac-router v4.
I want the following adress to build
http://localhost:7777/oceanside-yaht-club/booking/search
where oceanside-yaht-club can dynamicly change, depending on our customer.
But this is what I get now whit my try:
http://localhost:7777/oceanside-yaht-club/:pathParam/booking/search
Here is how I tried:
export enum Routes
{
Home = '',
BookingSearch = 'booking/search',
BookingOffers = 'booking/offers',
BookingExtras = 'booking/extras',
BookingContactDetails = 'booking/contact',
BookingBoatDetails = 'booking/boat',
BookingPayment = 'booking/payment',
BookingComplete = 'booking/complete',
BookingClose = 'booking/close'
}
export module Urls
{
export const home = `/${Routes.Home + ':pathParam?'}`;
export const bookingSearch = ':pathParam' + `/${Routes.BookingSearch}`;
export const bookingOffers = `/${Routes.BookingOffers}`;
export const bookingExtras = `/${Routes.BookingExtras}`;
export const bookingContactDetails = `/${Routes.BookingContactDetails}`;
export const bookingBoatDetaisl = `/${Routes.BookingBoatDetails}`;
export const bookingPayment = `/${Routes.BookingPayment}`;
export const bookingComplete = `/${Routes.BookingComplete}`;
export const bookingClose = `/${Routes.BookingClose}`;
}
export const IndexRoutes = () =>
<React.Fragment>
<Route exact path={ Urls.home } component={ App } />
<Route exact path={ Urls.bookingSearch } component={ Search } />
<Route exact path={ Urls.bookingOffers } component={ Offers } />
<Route exact path={ Urls.bookingExtras } component={ Extras } />
<Route exact path={ Urls.bookingContactDetails } component={ ContactDetails } />
<Route exact path={ Urls.bookingBoatDetaisl } component={ BoatDetails } />
<Route exact path={ Urls.bookingPayment } component={ Payment } />
<Route exact path={ Urls.bookingComplete } component={ Complete } />
<Route exact path={ Urls.bookingClose } component={ WindowsCloseDialog } />
</React.Fragment>
and this is how I push in the router history
const url: string = `${this.store.state.marinaData.MarinaUrlName}/${Urls.bookingSearch}`;
// const url: string = `oceanside-yaht-club/${Urls.bookingSearch}`; //for test
this.props.history.push(url);
I even tried this regex, but not figured out how to implement in my code
thnx
You cannot use the Route path param as it is directly while passing url to history.push, instead it needs a complete link.
You can change the code to
const url: string = `${this.store.state.marinaData.MarinaUrlName}/${Routes.BookingSearch}`;
this.props.history.push(url);
Related
I've looked online and most questions uses a different version of react-router-dom than what I'm using making the answer hard to find. What I want to do is simple, let's say a user is logged in then I wouldn't want that user to access the "sign-up" page and redirect them to the "home" page.
Here's the code I'm using that isn't working.
import { useAuth } from '../contexts/AuthContext';
import "firebase/auth";
import {Route, Navigate} from 'react-router-dom'
function AuthRoute ({element: Element, ...rest}) {
const { currentUser } = useAuth()
return (
<Route
{...rest}
render={props => {
return !currentUser ? <Element {...props} /> : <Navigate to="/" />
}}
></Route>
)
}
export default AuthRoute;
Here's how it's being called in App.js
return (
<Router>
<div className = "App">
<AuthProvider>
<Routes>
<Route path="/" element={<Home/>}/>
<AuthRoute exact path = "/sign_up" element= {SignUp} />
<Route exact path="/about" element={<About/>}/>
<Route exact path="/login" element={<SignIn/>}/>
</Routes>
</AuthProvider>
</div>
</Router>
);
It routes to sign_up but it doesn't matter if the user exists or not.
I don't know if you still need help with this but I found how to do it,
first your home route should be an exact path, then in AuthRoute() component you can do this:
export default function AuthRoute ({chidren}) {
const { currentUser } = useAuth()
if (currentUser){
return (children)
}else{
return <Navigate to='/sign_up' replace/>
}
}
then in App.js:
<AuthRoute exact path = "/sign_up" element= {SignUp} /> // should be :
<Route path='/sign_up' element={<AuthRoute> <Home/> </AuthRoute>}
</Route>
hope this can help anyone struggling with react-router v6 (like I did)
I am trying to limit user going back to the previous page,
It works but I can see previous page for millisecond and then current page reloads with
all API requests.
How can I prevent that behaviour?
import React, { Component } from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import { createBrowserHistory } from "history";
export default class Main extends Component {
componentDidMount() {
// const history = useHistory();
const history = createBrowserHistory();
history.listen((newLocation, action) => {
if (action === "PUSH") {
if (
newLocation.pathname !== this.currentPathname ||
newLocation.search !== this.currentSearch
) {
// Save new location
this.currentPathname = newLocation.pathname;
this.currentSearch = newLocation.search;
// Clone location object and push it to history
history.push({
pathname: newLocation.pathname,
search: newLocation.search,
});
}
} else {
// Send user back if they try to navigate back
history.go(1);
}
});
}
render() {
return (
<div>
<BrowserRouter>
<Switch>
<Route exact path="/" component={Page1} />
<Route path="/main/page2" component={Page2} />
<Route path="/main/page3" component={Page3} />
<Route path="/main/page4" component={Page4} />
<Route path="/main/page5" component={Page5} />
</Switch>
</BrowserRouter>
</div>
);
}
}
Try set the routes replace:
<Route path="/main/page2" component={Page2} replace={true}/>
<Route path="/main/page3" component={Page3} replace={true}/>
<Route path="/main/page4" component={Page4} replace={true}/>
<Route path="/main/page5" component={Page5} replace={true}/>
I have following routes in the application:
<Switch>
<Route path="/shops/:id">
<StoreDetails/>
</Route>
<Route path="/shops">
<Stores/>
</Route>
<Route path="/">
<Home/>
</Route>
</Switch>
how do I deep link /shops and /shops/:id URLs??
whith hooks :
import React from 'react';
export const test = props => {
const { match } = props;
const id = match.params.id;
return <></>;
};
How to acces query parameter in container, using react-router and react-kompose:
I am tying like this but it is not working:
routes.js
...
Meteor.startup(() => {
render(
<Router history={ browserHistory }>
<Route path="/" component={ App }>
<IndexRoute name="index" component={ Index } onEnter={ requireAuth } />
<Route name="documents" path="/documents" component={ Documents } onEnter={ requireAuth } />
<Route name="list-projects" path="/list-projects" component={ Projects } onEnter={ requireAuth } />
<Route name="add-project" path="/add-project" component={ AddProjectPage } onEnter={ requireAuth } />
<Route name="project-detail" path="/project/:projectId" component={ProjectDetailPage} onEnter={ requireAuth } />
<Route name="login" path="/login" component={ Login } />
<Route name="recover-password" path="/recover-password" component={ RecoverPassword } />
<Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } />
<Route name="signup" path="/signup" component={ Signup } />
<Route path="*" component={ NotFound } />
</Route>
</Router>,
document.getElementById('react-root')
);
});
container1.js
import { composeWithTracker } from 'react-komposer';
import { Projects } from '../../api/projects/projects.js';
import { ProjectDetail } from '../components/project-detail.js';
import { Loading } from '../components/loading.js';
import { Meteor } from 'meteor/meteor';
const composer = (params, onData) => {
const subscription = Meteor.subscribe('projects');
if (subscription.ready()) {
const project = Projects.find({_id:params._id}).fetch();
onData(null, { project});
}
};
export default composeWithTracker(composer, Loading)(ProjectDetail);
You probably figured it out by now, but you can get parameters inside props of the container like so, using your example just a little modified:
const composer = (props, onData) => {
const subscription = Meteor.subscribe('projects');
if (subscription.ready()) {
const project = Projects.find({_id:props.params.projectId}).fetch();
onData(null, { project});
}
};
export default composeWithTracker(composer, Loading)(ProjectDetail);
React Router will pass everything to its child components. props is an object, so you can access the params just by getting the value of props.params. You can access many more things inside your container depending on your needs.
I wonder if there's some way with React Router to get a list of all possible paths with the routes configuration?
For example, from this:
var routes = (
<Route name="/">
<DefaultRoute .../>
<Route name="about" .../>
<Route name="blog" .../>
</Route>
);
I'd like:
["/", "/about", "/blog"]
There are a couple of ways to do this:
The simplest: See your routes as an array by checking your props (this.props.routes). However, this includes a lot of extra data you aren't necessarily looking for.
More robust: Use a community-built tool like react-router-query, react-router-to-array, or react-router-sitemap. All have fairly robust read-me's you can dig into.
Someone asked a similar question on this thread with more detailed responses.
This seems to work for me, with v0.13:
var router = Router.create(routes);
var routePaths = [];
for (var i in router.namedRoutes) {
routePaths.push(router.namedRoutes[i].path);
}
//routePaths = ['/', '/about', '/blog']
I have written a function for this purpose:
/**
* Get list of paths
* #param routes {JSX.Element}
*/
const getRoutes = (routes) =>
{
const paths = new Set();
/**
* Walk in list of routes tree
* #param element {JSX.Element}
*/
const walkTree = (element) =>
{
if (element.props.children && element.props.children.length > 0)
{
element.props.children.forEach((elem) => walkTree(elem));
}
else if (element.props.path && typeof element.props.path === 'string')
{
paths.add(element.props.path);
}
}
walkTree(routes);
return paths;
};
A complete react sample (Tested with react 6):
import './App.scss';
import React from 'react';
import { Routes, Route } from 'react-router-dom';
import Login from './pages/login.page';
import Pricing from './pages/pricing.page';
import Register from './pages/register.page';
import Home from './pages/home.page';
import Dashboard from './pages/dashboard.page';
import Authenticator from './components/Authenticator.component';
import Profile from './pages/Profile.page';
const App = () => {
const routes = (
<Routes>
<Route exact path='/login' element={<Login />} />
<Route exact path='/register' element={<Register />} />
<Route exact path='/pricing' element={<Pricing />} />
<Route path='/' element={<Authenticator />}/>
<Route exact path='/dashboard' element={<Dashboard />} />
<Route exact path='/profile' element={<Profile />} />
</Route>
<Route path='/*' element={<Home />} />
</Routes>
);
/**
* Get list of paths
* #param routes {JSX.Element}
*/
const getRoutes = (routes) =>
{
const paths = new Set();
/**
* Walk in list of routes tree
* #param element {JSX.Element}
*/
const walkTree = (element) =>
{
if (element.props.children && element.props.children.length > 0)
{
element.props.children.forEach((elem) => walkTree(elem));
}
else if (element.props.path && typeof element.props.path === 'string')
{
paths.add(element.props.path);
}
}
walkTree(routes);
return paths;
};
console.log(getRoutes(routes));
return (
<div className="App">
<main id='main' className="main">
{ routes }
</main>
</div>
);
}
export default App;