I have a React app using React Router 4. A login modal is used to authenticate users. In order to support the UX requirements I've been given, I need to have the back button close the modal.
I was able to accomplish a login modal that supports this using a simple push state:
const {history,location} = this.props
const nextState = {showLogin: true}
history.push({...location, state: {...location.state, ...nextState}})
The behavior works as expected. HOWEVER… it would be ideal if pressing the forward button did not reopen the modal.
I don't see a way to pop a location off history with react router. But what I'd like to do is listen to route changes and if the location.state changes back to the showLogin modal being falsey, but the location is the same, it pops the previous location off history.
Use history.replace('') instead of history.push('') while going back.This way, the existing login route, will get replaced from the history stack
Related
I have a route ('profile/edit') that edits some information, and I want to prevent the user from reaching it by typing in the URL. For example, I want if the user types www.mywebsite.com/profile/edit/ in the URL, it will get redirected to www.mywebsite.com/. So I only want it to be accessible when you click the edit button. How do I do this? I'm using react route 6 for this project.
Is this URL accessible only if logged in?
Or do you need any param values to edit?
If yes, please double check your implementation, there you have other best methods to do it
Answer
Call a useNavigate in one of your root component (inside useEffect which only call once)
//rootComponent
const navigate = useNavigate()
useEffect(()=> {
navigate('/')
), [])
//Rest of your code
I'm (obviously) fairly new to ReactJS. I'm using Router v6 for navigation between pages. I have a case where the action of a button on Component A must depend on which component (B or C or ...) launched the page. But, using useNavigate, it doesn't seem to be possible to send a function to the target component A, only text fields seem to be allowed in the object. That is, the following doesn't work:
let navigate = useNavigate()
function nextClick() {
navigate('/UserProfile', {state:{
okClick: userProfileOkClick,
cancelClick: backButtonClick
}})
}
That is, I want to navigate to the UserProfile component, and pass the callback functions its buttons should use. It doesn't work -- in the UserProfile page, the state object is null.
So is there a way to navigate to a new page and dynamically change the button callbacks? I hope so...
Thanks!
I have a structure like this, there's a route like:
<Route path="/sample-route" component={ComponentA}/>
Then ComponentA has:
<ComponentA>
<ComponentB/>
<ComponentC>
<MaterialUIDrawer/>
</ComponentC>
</ComponentA>
ComponentC is used in 5 different routes as a child. The MaterialUIDrawer is showing based on a flag in a redux reducer. The problem I'm trying to solve is when the drawer is open, clicking back hides it but also navigates back. I tried solving it like this:
window.onpopstate = (e) => {
if (this.props.isOpen) {
this.props.toggleDrawer(false);
this.props.history.replace(this.props.match.url);
}
};
This has 2 issues:
If this is the first page you land on, it doesn't actually do anything, the function doesn't trigger
If you are on a different site and navigate to the url that contains the drawer, hitting Back moves you to a different URL (different domain)
I also tried setting a <Route/> in ComponentC and then the drawer lives there, but I didn't manage to get it to work, maybe the path is wrong. It felt like this might be the right way though, if path is /path1, then drawer lives in /path1/drawer, or /path2/drawer, etc.
I'm trying to find a way for the Back button in a browser to close the drawer (so execute a function I define) and override the default functionality.
I think you should be using props here instead of paths, so something like /path1?drawer=1, but you will definitely need to use history/location so that the back button can actually go back, so you are on the right trail.
I'm not sure what you are using for a browser history manager, but I would recommend tying off of that instead of leaning on the window pop-state. Your history module should be the source of truth and feed redux, not the other-way around IMO.
I was able to prevent navigation as per the v4 docs, but I'm trying to hook up a function so that I can use a modal instead of an alert.
Function:
abandonForm = (route) => {
this.props.showModal('confirm');
console.log('leaving..');
}
In my page:
<NavigationPrompt when={true} message={(location) => this.abandonForm('confirm')} />
this.props.showModal('confirm') activates the modal successfully, but behind the modal the page still transitions - how can I prevent transition until a button in the modal is clicked?
Browsers only allow navigation cancellation by means of the alert box that you've mentioned. This restriction is motivated by phishing/scamming sites that try to use javascript gimmicks to create user experiences that convincingly mimic something that a browser or the OS would do (whom the user trusts). Even the format of the text shown in the alert box is crafted so that it's obvious that it originates from the site.
Of course, as long as the current URL stays within your app, you have control over it using react-router's history. For example you can do the following on navigation:
allow the navigation without confirmation
immediately navigate back to the previous location, but now with a modal on top
navigate away for real this time when the user clicks on a button in the modal.
The disadvantage of this approach (leaving out the sheer complexity of it) is that the user will not get a confirmation dialog if they try to navigate to a different site entirely.
Use:
this.unBlock = this.props.history.block((location, navigateToSelectedRoute) => {
// save navigateToSelectedRoute eg this.navigateToSelectedRoute =
// navigateToSelectedRoute;
// use this.navigateToSelectedRoute() afterwards to navigate to link
// show custom modal using setState
});
and when unblocking is done then call this.unBlock() to remove the listener.
Documentation here for history api
If a user attempts to change the active page (window/tab/etc) from our page to another while myState is true, we want to notify/alert the user in React JS using react-router.
I tried implementing it with the help TransitionHook and React-router's Confirming Navigation article. Though these only point out / work when user wants to close the page or reload it. Whereas I need to know when user just temporarily leaves the page without necessarily closing it.
How can I achieve this?
If by "leaving the page", you mean that the page is open, but a different window has popped up, you could consider using the document.hasFocus property. Here is one way I handled a problem that was tangentially related:
componentDidMount: function (){
setInterval(()=>{
if (document.hasFocus()){
this.checkServerState();
}
},
},