Change path in react router without causing re-render? - reactjs

I have the following route:
<Route path="/cases" component={Cases} />
This route handles the following example paths
/cases
/cases/1
I have an iframe in this route that is responsible for handing all user interactions. On a location change in the iframe, the iframe posts a message to the parent window notifying it that the url has changed.
I want to be able to change the route in the parent window without re-rendering the iframe.
This is my current solution
this.props.history.replace(pathnameFromIframe);
shouldComponentUpdate = () => {
return false;
}
This solution works but it goes against the React docs:
shouldComponentUpdate ... method only exists as a performance
optimization. Do not rely on it to “prevent” a rendering, as this can
lead to bugs.
https://reactjs.org/docs/react-component.html#shouldcomponentupdate
Can I solve this some other way?
Is it perhaps possible to change the route without adding the route as a prop in the component? This would solve the problem I believe.

i think hashHistory what u need? if im not mistaken
import { hashHistory } from 'react-router';
hashHistory.push({
pathname:"/url-url",
});

Related

React Router: this.props.location.state is null

I am using react-router 2.4.0 and I am trying to pass in some state to my route on a click event. It passes in pathname and query correctly but state is null.
Below is my handler function
clickHandler: function() {
var navigate = { pathname: '/view/report',
query: { filter: "filter-val"},
state: {"field": this.state.field}
}
this.props.router.push(navigate);
In my component that renders the route, inside getInitialState I am trying to access the state but it comes up as null.
I logged the this.state.field and it is present after the button press but before routing. I also logged this.props.location inside thegetInitialState of the routed component and it has non-null values for things like query, pathname, etc. but state (this.props.location.state to be specific) shows up as null.
Is there something special I need to do to set an object inside state of the router's location?
v2.4.0 is an old version. While I'm not aware of any reason why this would be causing your error, it might help to try upgrade to v3 (just v2 with v1's deprecated code removed).

Angular 2 App Reloading on Route Change

I have an angular 2 app with the following routes:
#RouteConfig([
new Route({ path: '/', component: Home, name: 'Home', useAsDefault: true}),
new Route({ path: '/employees', component: ViewEmployees, name: 'ViewEmployees'}),
new Route({ path: '/employees/add', component: AddEmployee, name: 'AddEmployee'}),
])
among others. When I change routes in the following way:
<a [routerLink]="['ViewEmployees']">View Employees</a>
There are no issues. I can change routes in this way from either the home page or the AddEmployee route. The issue comes when I'm in the AddEmployee route and try to change routes in a programmatic way like this:
import {Router} from 'angular2/router';
...
constructor(private _router:Router) {}
...
navigate() {
this._router.navigate(['ViewEmployees']);
}
it doesn't work. It sends me to the ViewEmployees view and then reloads the entire app. If I do that same programmatic route change from the Home component I don't have any issues; the app doesn't reload.
Does anyone have any ideas why it would do this in just this one case? I need it to work so that I can save the employee that's added and then go back to the employee list view.
Thanks in advance for the help!
Do you call navigate() from within a <form> Tag?
I had the same Problem. There exist some issues describing this behavior on Angular2s GitHub but they are all closed because they belong to the old router. The page reload seems to occur when you use router.navigate() inside a function called by a submit button inside a form. This can cause the browser to append a ? at the end of the URL and reload it.
The solution is very simple: Just return false at the end of your navigate() function. This prevents the bowser to use it's default action when submitting forms. Usually angular stops such default behavior but strangely not in this case.
Have you set the <base href>?
As mentioned in the Router guide
Add the following code to your index.html after the opening head tag:
<base href="/">
From RouterLink docs:
The first route name should be prepended with /, ./, or ../. If the route begins with /, the router will look up the route from the root of the app. If the route begins with ./, the router will instead look in the current component's children for the route. And if the route begins with ../, the router will look at the current component's parent.
Use:
<a [routerLink]="['/ViewEmployees']">View Employees</a>

Can I use an HTML form's action property to move between React Routes?

I'm trying to build a React app, and getting some trouble with React Router.
First of all, my url always has some weird hashstring at its' end.
For example:
http://localhost:3000/#/?_k=gb3epe
Also, I'm not sure whether the hashtag in the url and the following gibberish are part of the same problem or if they're related to 2 different problems. (I'm currently using React-Router v1.0).
Secondly, I think that the weird URL is preventing me from using the "action" property on forms, and would also like to know if there is a better way to move around React renders then relaying on forms.
Thanks.
If we're talking about react-router v1.0, then to remove this hash string you should pass a { queryKey: false } parameter to the createBrowserHistory function.
var createBrowserHistory = require('history/lib/createBrowserHistory');
ReactDOM.render(
<Router history={ createBrowserHistory({ queryKey: false }) }
routes={ ReactRoutes } />,
document.getElementById('some-container')
);
To move between routes react-router provides Link component which you can use inside your components.

How do I add redirect to react-router dynamically?

I have sign in component, which should be available for unauthenticated users. And right after the authentication this component should become unavailable.
var routes = (
<Route handler={App}>
<Route name="signIn" handler={signIn}/>
{/* redirect, if user is already authenticated */}
{ localStorage.userToken ? (
<Redirect from="signIn" to="/user"/>
) : null
}
</Route>
);
Router.run(routes, (Handler, state) => {
React.render(<Handler {...state}/>, document.getElementById('main'));
});
This code works perfect if user have reloaded webapp for any reason after the authentication, but of course it doesn't if user didn't reload the webapp.
I've tried to use this.context.router.transitionTo right to the SignUp component, but it works awful - the component gets rendered, then this script is getting executed.
So I want to add the redirect right into the routes variable to make the router redirect without even trying to render the component.
Instead of checking your auth-flow and conditionally rendering particular routes, I would recommend another approach:
If you're using react-router 0.13.x, I would recommend using the willTransitionTo methods on your components when you need to check authentication. It is called when a handler is about to render, giving you the opportunity to abort or redirect the transition (in this case, check if user is authenticated, redirect to another path if not). See auth-flow example here: https://github.com/ReactTraining/react-router/blob/v0.13.6/examples/auth-flow/app.js
For versions >0.13.x, it would be onEnter and Enterhooks. See the auth-flow example here: https://github.com/rackt/react-router/blob/master/examples/auth-flow/app.js
Basically you move the auth-check flow away from your routes variable, and into transition events/hooks. Before the route handler actually gets rendered, check the auth, and redirect the user to another route.

Don't render any view by default - reactjs

I have a container div with some static HTML. I don't want my react router to do anything if default location is /. It expects a default view which I don't have. Is there an easy solution.
I tried this but it doesn't work with back/forward browser button?
var initApp = function() {
Router.run(routes, function(Handler) {
if(Router.HashLocation.getCurrentPath() !== '/') {
React.render(<Handler/>, document.getElementById('top-container'));
}
});
}
Seems hacky to suggest - but have you tried passing a mocked component (not inheriting from React.Component) with a no-op render: function() {}? Otherwise, I think React will replace your wrapper's innerHTML.
On the other hand - are you rendering server-side? If so, the output of a "dumb" component handler for '/' which prints the same markup as your container currently holds, would quite literally be static HTML anyway, despite being rendered by React.

Resources