Meteor, React-Router , react-komposer - passing parameter - reactjs

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.

Related

How can I disable back button in React Router?

I have tried to disable back button in browser but it just reloading the page to the path="/"
How can I disable back button of the browser, so when user clicks it nothing happens??
export default class Main extends Component {
componentDidMount() {
const history = createBrowserHistory();
history.listen((newLocation, action) => {
if (action === "POP") {
history.go(0);
}
});
}
render() {
return (
<div>
<Router>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/main/component1" component={Component1} />
<Route path="/main/component2" component={Component2} />
<Route path="/main/component3" component={Component3} />
</Switch>
</Router>
</div>
);
}
}
You can do it using react-router-dom
import { useHistory } from "react-router-dom";
let history = useHistory();
history.replace("/login");

React won't render my newly created component accessed via route

Basically, I'm working on the DataTurks project but I've stumbled upon some problems linked to the frontend app named bazaar. I'm trying to create a new component and add a new route for it so I can access it. This is my code for my routes:
import React from 'react';
import {IndexRoute, Route} from 'react-router';
// import { isLoaded as isAuthLoaded, load as loadAuth } from 'redux/modules/auth';
import {
App,
Home,
NotFound,
TaggerLogin,
TaggerSpace,
TaggerCreate,
TaggerImport,
TaggerStats,
TaggerExport,
TaggerProjects,
TaggerAdd,
TaggerOveriew,
TaggerVisualize,
TaggerEdit,
TaggerOrg,
TaggerOrgProject,
TaggerError,
TaggerKeyBind,
TaggerContributors,
ConfirmMail
} from 'containers';
export default (store) => {
const requireLogin = (nextState, replace, cb) => {
const { auth: { user }} = store.getState();
if (!user) {
// oops, not logged in, so can't be here!
replace('/projects/login');
}
cb();
};
/**
* Please keep routes in alphabetical order
*/
return (
<Route path="/" component={App}>
<Route path="confirm" component={ConfirmMail}/> //THIS IS THE COMPONENT I'M TRYING TO ACCESS
{ /* Home (main) route */ }
<IndexRoute component={Home}/>
{ /* Routes requiring login */ }
<Route onEnter={requireLogin}>
<Route path="projects/create" component={TaggerCreate}/>
<Route path="projects/edit" component={TaggerEdit}/>
<Route path="projects/:orgName/create" component={TaggerCreate}/>
<Route path="projects/:orgName/import" component={TaggerImport}/>
<Route path="projects/:orgName/:projectName/edit" component={TaggerEdit}/>
<Route path="projects/:orgName/:projectName/keybind" component={TaggerKeyBind}/>
</Route>
{ /* Dataturks tool */}
<Route path="projects/login" component={TaggerLogin}/>
<Route path="projects/import" component={TaggerImport}/>
<Route path="projects/space" component={TaggerSpace}/>
<Route path="projects/stats" component={TaggerStats}/>
<Route path="projects/export" component={TaggerExport}/>
<Route path="projects" component={TaggerProjects}/>
<Route path="projects/add" component={TaggerAdd}/>
<Route path="projects/overview" component={TaggerOveriew}/>
<Route path="projects/visualize" component={TaggerVisualize}/>
<Route path="projects/errors" component={TaggerError}/>
<Route path="projects/:orgName" component={TaggerOrg} />
<Route path="projects/:orgName/:projectName" component={TaggerOrgProject} />
<Route path="projects/:orgName/:projectName/space" component={TaggerSpace}/>
<Route path="projects/:orgName/:projectName/export" component={TaggerExport}/>
<Route path="projects/:orgName/:projectName/overview" component={TaggerOveriew}/>
<Route path="projects/:orgName/:projectName/visualize" component={TaggerVisualize}/>
<Route path="projects/:orgName/:projectName/contributors" component={TaggerContributors}/>
{ /* Catch all route */ }
<Route path="*" component={NotFound} status={404} />
</Route>
);
};
What I'm trying to access is ConfirmMail component and route. The ConfirmMail component:
import React from 'react';
export default function ConfirmMail() {
const styles = require('./ConfirmMail.scss');
return (
<div className="container">
<div className={styles.loading + ' text-center'}>
<span className="glyphicon glyphicon-repeat glyphicon-refresh-animate gi-3x">
CONFIRMED
</span>
</div>
</div>
);
}
Also, the client.js:
import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import createStore from './redux/create';
import ApiClient from './helpers/ApiClient';
import {Provider} from 'react-redux';
import { Router, browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import { ReduxAsyncConnect } from 'redux-async-connect';
import useScroll from 'scroll-behavior/lib/useStandardScroll';
import {persistStore} from 'redux-persist';
import getRoutes from './routes';
import { Segment } from 'semantic-ui-react';
const client = new ApiClient();
const _browserHistory = useScroll(() => browserHistory)();
console.log('window data is', window._data);
const store = createStore(_browserHistory, client, window.__data);
const history = syncHistoryWithStore(_browserHistory, store);
class AppProvider extends React.Component {
constructor() {
super();
this.state = { rehydrated: false };
}
componentWillMount() {
persistStore(store, { blacklist: ['routing', 'dataturksReducer'] }, () => {
this.setState({ rehydrated: true });
});
}
render() {
const component = (
<Router render={(props) =>
<ReduxAsyncConnect {...props} helpers={{client}} filter={item => !item.deferred} />
} history={history}>
{getRoutes(store)}
</Router>
);
if (!this.state.rehydrated) {
return (<div><Segment basic loading/></div>);
} else if (this.state.rehydrated) {
console.log('rehydrating ', component);
return (
<Provider store={store} key="provider">
{component}
</Provider>);
}
}
}
const dest = document.getElementById('content');
ReactDOM.render(
<AppProvider />,
dest
);
// const persistor = persistStore(store, {}, () => { this.rehydrated = true; });
This is the main App.js component in this project.
So when I access localhost/confirm, I don't get a 404 not found page but I get an empty page. Earlier I've tried to console.log a few things but it didn't work either. I've been working on this my whole day and I didn't manage to make it work. Does someone know what am I doing wrong?
Did you try to add / in Route path?
<Route path="/confirm"
You need to add / before every route. That's why it is not getting the component you want. So modify your code by adding / like the following
<Route path="/confirm" component={ConfirmMail}/>
And another thing that I recommend you to do is enclose your routers inside <Switch></Sitch>. If the URL is /confirm, then all routes below it will be rendered. This is by design, allowing us to compose s into our apps in many ways, like sidebars and breadcrumbs, bootstrap tabs, etc.
Occasionally, however, we want to pick only one to render. If we’re at /confirm we don’t want to also match /:orgName If so you will end up with 404 error.
Here’s how to do it with Switch:
return (
<Switch>
<Route path="/" component={App}/>
<Route path="confirm" component={ConfirmMail}/> //THIS IS THE COMPONENT I'M TRYING TO ACCESS
{ /* Home (main) route */ }
<IndexRoute component={Home}/>
{ /* Routes requiring login */ }
<Route onEnter={requireLogin}>
<Route path="projects/create" component={TaggerCreate}/>
<Route path="projects/edit" component={TaggerEdit}/>
<Route path="projects/:orgName/create" component={TaggerCreate}/>
<Route path="projects/:orgName/import" component={TaggerImport}/>
<Route path="projects/:orgName/:projectName/edit" component={TaggerEdit}/>
<Route path="projects/:orgName/:projectName/keybind" component={TaggerKeyBind}/>
</Route>
{ /* Dataturks tool */}
<Route path="projects/login" component={TaggerLogin}/>
<Route path="projects/import" component={TaggerImport}/>
<Route path="projects/space" component={TaggerSpace}/>
<Route path="projects/stats" component={TaggerStats}/>
<Route path="projects/export" component={TaggerExport}/>
<Route path="projects" component={TaggerProjects}/>
<Route path="projects/add" component={TaggerAdd}/>
<Route path="projects/overview" component={TaggerOveriew}/>
<Route path="projects/visualize" component={TaggerVisualize}/>
<Route path="projects/errors" component={TaggerError}/>
<Route path="projects/:orgName" component={TaggerOrg} />
<Route path="projects/:orgName/:projectName" component={TaggerOrgProject} />
<Route path="projects/:orgName/:projectName/space" component={TaggerSpace}/>
<Route path="projects/:orgName/:projectName/export" component={TaggerExport}/>
<Route path="projects/:orgName/:projectName/overview" component={TaggerOveriew}/>
<Route path="projects/:orgName/:projectName/visualize" component={TaggerVisualize}/>
<Route path="projects/:orgName/:projectName/contributors" component={TaggerContributors}/>
{ /* Catch all route */ }
<Route path="*" component={NotFound} status={404} />
</Switch>
);

Navigate to new URL from within MemoryRouter structure

When a user completes a booking process and navigate to the confirmed details view. I need the URL to change. This is proving to be difficult to work around as the routing in done through MemoryRouter which can neither read, nor write to the URL. I need to break one of the views out and have the browser navigate to this new view.
I have tried breaking out from one router and creating a second that would return based on the original URL, then tried the very hacky window.location and direct the url to the new router.
import React from 'react';
import { MemoryRouter, Route, Switch } from 'react-router-dom';
import {
Page,
StartScreen,
StoreSearch,
ServiceSelector,
StoreSelector,
OptionSelector,
AppointmentForm,
AppointmentDetails,
ConfirmationScreen,
ErrorScreen,
} from 'components';
import { WithPageTitle, ScrollToTop } from 'containers';
import { services } from 'utilities';
const NewAppRouter = () => {
return (
<MemoryRouter>
<ScrollToTop>
<Switch>
<Route exact path="/" component={StartScreen} />
<WithPageTitle>
{pageTitle => (
<Page pageTitle={pageTitle}>
<Route path="/zip" component={StoreSearch} />
<Route path="/services" component={() => ServiceSelector({
services: services.services,
withBackButton: true,
backTo: "/zip"
})} />
<Route path="/stores" component={StoreSelector} />
<Route path="/options" component={OptionSelector} />
<Route path="/form" component={AppointmentForm} />
<Route path="/details" component={AppointmentDetails} />
{/* <Route path="/confirmation" component={ConfirmationScreen} /> */}
<Route path="/error" component={ErrorScreen} />
</Page>
)}
</WithPageTitle>
</Switch>
</ScrollToTop>
</MemoryRouter>
)
}
const AppRouter = () => {
if(window.location.href="http://localhost:9998"){
return (
<NewAppRouter />
)
} else if (window.location.href="http://localhost:9998/confirmation") {
return (
<ConfirmRouter />
)
} else {
return console.error('Route Not Found')
}
}
export default AppRouter;

React router v4 dynamic parameter

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);

Difference between declaring JSX code in variable and in React component

I've recently started playing around with Redux and quickly came across this error message : Warning: You cannot change <Router routes>; it will be ignored (I'm also using react-router). After a little search, I understood I had to declare my routes in a variable so they wouldn't get re-rendered.
So here's my code :
Routing.js
import React from 'react';
import { Router, browserHistory, Route, IndexRoute, Redirect } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import RouterUtils from 'src/utils/js/RouterUtils';
import MainContent from 'src/common/main-content/js/MainContent';
// modules loaded lazily
import IndexPage from 'src/views/index/js/IndexPage';
import Page403 from 'src/views/403/js/403';
import Page404 from 'src/views/404/js/404';
import LoginPage from 'src/views/login/js/LoginPage';
import GetBusiness from 'src/route-fetch-components/business-get/js/GetBusiness';
import BusinessesPage from 'src/views/businesses-list/js/BusinessesPage';
import BusinessPage from 'src/views/business-details/js/BusinessPage';
import GetJobSeeker from 'src/route-fetch-components/jobseeker-get/js/GetJobSeeker';
import JobSeekersPage from 'src/views/jobseekers-list/js/JobSeekersPage';
import JobSeekerPage from 'src/views/jobseeker-details/js/JobSeekerPage';
import GetJobOffer from 'src/route-fetch-components/job-offer-get/js/GetJobOffer';
import JobOffersPage from 'src/views/job-offers-list/js/JobOffersPage';
import JobOfferPage from 'src/views/job-offer-details/js/JobOfferPage.js';
import JobOfferCreatePage from 'src/views/job-offer-create/js/JobOfferCreatePage';
const lazyLoadComponent = lazyModule =>
(location, cb) => {
lazyModule(module => {
cb(null, module.default);
});
};
const redirectTo404 = () => {
RouterUtils.redirect('/404');
};
const routes = (
<div>
<Route path="/" component={MainContent}>
<IndexRoute getComponent={lazyLoadComponent(IndexPage)} />
<Route path="businesses">
<IndexRoute getComponent={lazyLoadComponent(BusinessesPage)} />
<Route path=":user_id" getComponent={lazyLoadComponent(GetBusiness)}>
<IndexRoute getComponent={lazyLoadComponent(BusinessPage)} />
<Route path="job-offers">
<IndexRoute onEnter={() => redirectTo404()} /> // TODO: Add a component to list all job offers related to a business
<Route path=":job_offer_id" getComponent={lazyLoadComponent(GetJobOffer)}>
<IndexRoute getComponent={lazyLoadComponent(JobOfferPage)} />
</Route>
</Route>
</Route>
</Route>
<Route path="jobseekers">
<IndexRoute getComponent={lazyLoadComponent(JobSeekersPage)} />
<Route path=":user_id" getComponent={lazyLoadComponent(GetJobSeeker)}>
<IndexRoute getComponent={lazyLoadComponent(JobSeekerPage)} />
/*<Route path="applications">
<IndexRoute onEnter={() => redirectTo404()} /> // TODO: Add a component to list all applications related to a jobseeker
<Route path=":application_id" getComponent={lazyLoadComponent(JobOfferPage)} />
</Route>*/
</Route>
</Route>
<Route path="job-offers">
<IndexRoute getComponent={lazyLoadComponent(JobOffersPage)} />
<Route path="create" getComponent={lazyLoadComponent(JobOfferCreatePage)} />
</Route>
<Route path="403" getComponent={lazyLoadComponent(Page403)} />
<Route path="404" getComponent={lazyLoadComponent(Page404)} />
</Route>
<Route path="login" getComponent={lazyLoadComponent(LoginPage)} />
<Redirect from="*" to="404" />
</div>);
export default class Routing extends React.Component {
constructor(props, context) {
super(props);
this.history = syncHistoryWithStore(browserHistory, context.store);
}
render() {
return (
<Router history={this.history}>
{routes}
</Router>
);
}
}
Routing.contextTypes = {
store: React.PropTypes.object.isRequired,
};
It works perfectly fine, but I would now like to make a component ouf of my routes. So I just take the JSX code out in a new component :
Routing.js
import React from 'react';
import { Router, browserHistory } from 'react-router';
import { syncHistoryWithStore } from 'react-router-redux';
import Routes from './Routes';
const routes = <Routes />;
export default class Routing extends React.Component {
constructor(props, context) {
super(props);
this.history = syncHistoryWithStore(browserHistory, context.store);
}
render() {
return (
<Router history={this.history}>
{routes}
</Router>
);
}
}
Routing.contextTypes = {
store: React.PropTypes.object.isRequired,
};
Routes.js
import React from 'react';
import { Route, IndexRoute, Redirect } from 'react-router';
import RouterUtils from 'src/utils/js/RouterUtils';
import MainContent from 'src/common/main-content/js/MainContent';
// components loaded lazily
import IndexPage from 'src/views/index/js/IndexPage';
import Page403 from 'src/views/403/js/403';
import Page404 from 'src/views/404/js/404';
import LoginPage from 'src/views/login/js/LoginPage';
import GetBusiness from 'src/route-fetch-components/business-get/js/GetBusiness';
import BusinessesPage from 'src/views/businesses-list/js/BusinessesPage';
import BusinessPage from 'src/views/business-details/js/BusinessPage';
import GetJobSeeker from 'src/route-fetch-components/jobseeker-get/js/GetJobSeeker';
import JobSeekersPage from 'src/views/jobseekers-list/js/JobSeekersPage';
import JobSeekerPage from 'src/views/jobseeker-details/js/JobSeekerPage';
import GetJobOffer from 'src/route-fetch-components/job-offer-get/js/GetJobOffer';
import JobOffersPage from 'src/views/job-offers-list/js/JobOffersPage';
import JobOfferPage from 'src/views/job-offer-details/js/JobOfferPage.js';
import JobOfferCreatePage from 'src/views/job-offer-create/js/JobOfferCreatePage';
const lazyLoadComponent = lazyModule =>
(location, cb) => {
lazyModule(module => {
cb(null, module.default);
});
};
const redirectTo404 = () => {
RouterUtils.redirect('/404');
};
const Routes = () => (
<div>
<Route path="/" component={MainContent}>
<IndexRoute getComponent={lazyLoadComponent(IndexPage)} />
<Route path="businesses">
<IndexRoute getComponent={lazyLoadComponent(BusinessesPage)} />
<Route path=":user_id" getComponent={lazyLoadComponent(GetBusiness)}>
<IndexRoute getComponent={lazyLoadComponent(BusinessPage)} />
<Route path="job-offers">
<IndexRoute onEnter={() => redirectTo404()} /> // TODO: Add a component to list all job offers related to a business
<Route path=":job_offer_id" getComponent={lazyLoadComponent(GetJobOffer)}>
<IndexRoute getComponent={lazyLoadComponent(JobOfferPage)} />
</Route>
</Route>
</Route>
</Route>
<Route path="jobseekers">
<IndexRoute getComponent={lazyLoadComponent(JobSeekersPage)} />
<Route path=":user_id" getComponent={lazyLoadComponent(GetJobSeeker)}>
<IndexRoute getComponent={lazyLoadComponent(JobSeekerPage)} />
/*<Route path="applications">
<IndexRoute onEnter={() => redirectTo404()} /> // TODO: Add a component to list all applications related to a jobseeker
<Route path=":application_id" getComponent={lazyLoadComponent(JobOfferPage)} />
</Route>*/
</Route>
</Route>
<Route path="job-offers">
<IndexRoute getComponent={lazyLoadComponent(JobOffersPage)} />
<Route path="create" getComponent={lazyLoadComponent(JobOfferCreatePage)} />
</Route>
<Route path="403" getComponent={lazyLoadComponent(Page403)} />
<Route path="404" getComponent={lazyLoadComponent(Page404)} />
</Route>
<Route path="login" getComponent={lazyLoadComponent(LoginPage)} />
<Redirect from="*" to="404" />
</div>
);
export default Routes;
Ahhhhh... Cleaner. Except it doesn't work anymore. My page doesn't load, and I get this error :
Warning: [react-router] Location "/" did not match any routes
Now I'm wondering : what's the difference between assigning my JSX code to a var, as const routes = (<div>...</div>) and declaring it in a React Component (actually a pure function here, but I tested both)?
Thanks in advance for your time!

Resources