Change the route but dont navigate in React + React Router Dom - reactjs

I am using a multiple step form, this one: https://material-ui.com/getting-started/templates/checkout/
It works perfectly. But i need to update the url when I change the step.
My first thought was to use a redirect, but it seems very complicated.
if (newCheckout) return <Redirect to={`checkout/${newCheckout}`} />;
Is there any way to achieve that without redirecting?.
I dont want to lose the data from my component. Just update the route.. .

Related

React - How to navigate using a custom component instead of react-router-dom

I have a rooms list that I iterate, rendering the different rooms like this:
<Room room={room} key={room.id}/>
I want each room to redirect to their corresponding path (/rooms/:id). The only way of redirecting elements is via react-router-dom but I feel there must be a better way of achieving redirection in this case.
React router works fine, only thing you need is pass id to link
<Route path="/RoomsList/:roomId" element={<RoomCard/>}/>
in RoomCard you use hook
const {roomId} = useParams();
and change the component depending on the id.

How to listen to route changes in react router v5?

I need to throw out a warning when I try to go to another page or endpoint if the document is not saved
There's a declarative approach of how one can prevent navigation using <Prompt> component.
<Prompt
when={isBlocking}
message={location =>
`Are you sure you want to go to ${location.pathname}`
}
/>
isBlocking usually comes from the state of a component that needs to be conditionally rendered.
You can see a working example here.

How to use React Router to route to another url AND re-render page with NEW component?

In App.js, I have a button that if you click, should redirect users using React-Route to another URL, /landingpagehahaha, and should render a component called LandingPage. However, neither the URL is being changed in my browser nor the correct component being rendered. The behavior right now when you click the button is that the current page gets re-rendered, not the correct LandingPage component.
The React-Route logic is placed in a function called routeChange(). I put 2 alert() statements in it which get called, telling me that it is getting inside that function. However, nothing else changes.
I have tried using this.props.history.push("./LandingPage"); in routeChange() but it doesn't get past that statement. It appears like it behaves like response.json(), which returns from the function after it runs.
I have also tried using withRouter(), but I get a weird error that I can't call Route inside Router. I was unable to resolve that issue.
// Changes route
routeChange() {
alert("HELLO BEFORE");
alert("HELLo");
return (
<div>
<Route path="/landingpagehahaha" component={LandingPage} />;
</div>
);
}
// The button that is supposed to bring user to next page
<button onClick={this.routeChange}>Go To Next Page</button>
You need to return the Redirect component from your render function, or as use the history api to push the route into your navigation stack.
The first thing you should do, is move out the route declaration, and play it higher up in your component hierachy, you have to make sure the route declaration is rendered, when you're trying to go to the route.
Instead of using the history api, you could also use the Redirect component provided by react-router. I've made a small example here.
https://codesandbox.io/s/bold-paper-kxcri

React Router 4 - How to append path to existing query

I am writing an webapp that only loads when you are on a url with a query, for example:
http://localhost/site/?runapp=1
And I want to use React Router 4 in the app, but when I add a Route with a path, such as:
<Route path="/somepage" component={somePage} />
And the user clicks a:
<Link to="somepage">
to load that Route the url gets converted to:
http://localhost/site/somepage
And on refresh, the app stops working as the query is gone. How can I make React Router 4 append the paths to the needed query? I know it doesn't look pretty, but essentially I need it to route like to this url:
http://localhost/site/?runapp=1/somepage
That would make it all work, I think.
Is there a way to achieve this?
EDIT: I realized that I can simply add the ?runapp=1 in every Link to get the url to be "correct", i.e:
<Link to="?runapp=1/somepage">
but it seems hacky and doesn't allow the Route to load.

Automatic Deep Sub-Route Redirecting in React-Router

I have recently been transitioning a project from AngularJS + UI-Router+ UI-Router-Extras to React + React-Router.
One of the better features in UI-Router-Extras that I'd like to bring to React-Router is called
Deep State Redirect. In this feature, when navigating to a route which has subroutes, the application knows to redirect the user to the last subroute of it that was visited, or if none of its subroutes have yet been visited then it redirects to its first subroute to have been registered.
So for example if the loaded routing tree looks like this:
/main
|_/main_sub_1
|_/main_sub_2
/secondary
and the user starts at route /main/main_sub_2, then goes to /secondary, then goes to /main, they will be automatically redirected to /main/main_sub_2 since /main/main_sub_2 is the last subroute of /main to have been visited.
I know that I could implement this in react router by using
<IndexRedirect to={getLastSubRoute(parentRoute)}> where parentRoute is the full path of the parent <Route> tag, and getLastSubRoute is self-explanitory, but the problem with this is that I would need to add such an <IndexRedirect> tag to every single route I create, which is not optimal since the routes are loaded dynamically, there may be up to 100 subroutes, and much of the application's routing will be written by other people who I shouldn't be relying on to remember to add that tag under every <Route> tag they write.
Ideally, I should be able to apply some function or mixin to the base <Router> tag in the React routing definition to add this functionality to all routing underneath it, but I'm not sure where to start. How might I solve this problem?
Your best bet and possibly the simplest solution would be to set an onChange hook on one of the top level routes. The hook would get called with the next parameter, which would be the next route that the user would be going to.
You would also have the hierarchical structure of routes there (navigating through to parent and children of the parent), so you could dynamically redirect using the replace function, that gets passed in as a parameter also.
I implemented something similar for permission and role management. What I also did was to .bind my store to the function that I pass into the route hook. You could possibly store the route you'd like to redirect to on the user in the state tree. Basically what you refer to as getLastSubRoute.
...
<Route onChange={myRedirectFunctionThatHasStoreBound} .. >
... // other routes
</Route>
...
function myRedirectFunctionThatHasStoreBound(store, prev, next, replace, callback) {
const user = store.getState().user;
const redirectTo = getLastSubRouteForRoute(user, next);
if (redirectTo) {
replace(redirectTo);
}
// don't forget this is you list callback as a param
// your app might stop working, explanation below
callback();
}
If callback is listed as a 4th argument, this hook will run asynchronously, and the transition will block until callback is called.
EDIT: Keep in mind that this will only work if you are using react-router that's newer than or equal to in version to react-router 2.1

Resources