Prevent Navigation


In this article, we will continue discussing about Routing. 

In our last article, we have discussed about how to Protect our routes so that only Logged In Users can access Home or Edit Profile Components. 

If we look at the Output of our routing Program we have developed in the last session, we have three components named login, home and editprofile. When we enter the valid credentials we are navigating users to home component. From home Component, user can navigate to Edit Profile Component as well. 

Now assuming that EditProfile Component looks this way, user can change his Profile details and update them by Clicking on Update. 

Now imagine that we made some changes to the User Profile details and by mistake we clicked on home tab. Then we get navigated to home component. Now if we go back to edit profile component, we don’t find our changes. Its because the component gets unmounted when we go away from a component. But it would have been good if our application prompts a notification to the user that there are some unsaved changes. Do you really want to go away. So that user can take appropriate action. 

In this article, we will understand prevent the user from navigating away from a page when there are some unsaved changes

Lets open index.js file from our demo-project.

Lets go to Edit Profile Component, create one state variable which holds user information like first name, last name and email Id.

Lets add the required input elements and let the input elements display the user details by reading from the state variable.

We will add a button to update the user details.

We will implement the onDataChange function and with in that function, we will update the state object. 

Lets add one more state variable using which we can track if the data is changed by the user or not and we will initialize it to false.

When there is a change of user data, we will set isDataChanged to true. 

We will set this to false again when user clicks on update button. 

we use Prompt Component to prompt a notification when the transition happens. 

We will import prompt from react router dom. 

We show the Prompt component when we have unsaved changes. We can pass the message as well. 

Save the changes, navigate to the browser. 

Navigate to the edit profile component. Make some changes to the user profile. Now if we click on home link, we get the notification. 

We can save the user details. Now if we click on home link, we get navigated without any notification. 

import React, { useState, Component } from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter, Link, NavLink, Switch, Route, Redirect, Prompt} from 'react-router-dom';

const authentication={
  isLoggedIn:false,
  onAuthentication(){
    this.isLoggedIn=true;
  },
  getLogInStatus(){
    return this.isLoggedIn;
  }
}
function SecuredRoute(props){
  return(
    <Route path={props.path} render={data=>authentication.getLogInStatus()?(
      <props.component {...data}></props.component>):
      (<Redirect to={{pathname:'/'}}></Redirect>)}></Route>
  )
}
function LogIn(props){
  const [loginData,setLoginData]=useState({username:'',password:''});

  function changeLogInData(e){
    setLoginData({...loginData,[e.target.name]:e.target.value});
  }

  function onLogIn(){
    fetch("https://localhost:44306/api/Test",{
      method:'POST',
      headers:{'Content-type':'application/json'},
      body:JSON.stringify(loginData)
    }).then(r=>r.json()).then(result=>{
      if(result){
        authentication.onAuthentication();
        props.history.push('/home');
      }
      else{
        alert('Invalid UserName or PassWord');
      }
    });
  }

  return(
    <div>
      <h2>Welcome to LogIn...</h2>
      <p>
        <label>UserName : <input type="text" value={loginData.username} 
                          name="username" onChange={changeLogInData}></input></label>
      </p>
      <p>
        <label>PassWord : <input type="text" value={loginData.password} 
                          name="password" onChange={changeLogInData}></input></label>
      </p>
      <button onClick={onLogIn}>LogIn</button>
    </div>
  )
}

function Home(props){
  function onNext(){
    props.history.replace('/editprofile');
  }
  return(
    <div>
      <h2>Welcome to Home...</h2>  
      <button onClick={onNext}>Next</button>    
    </div>
  );
}
function EditProfile(){

  let [isDataChanged,setDataChanged]=useState(false);
  
  let [userInfo,setUserInfo]=useState({firstName:'Pragim',
                                      lastName:'Technologies',
                                      userName:'Pragim Tech', 
                                      emailId:'Pragim@gmail.com',
                                      contactNo:'+91-9945699393'});

  
  function saveChanges(){
    setDataChanged(false);
  }

  function onUserDataChange(e){
    setUserInfo({...userInfo,[e.target.name]:e.target.value});
    setDataChanged(true);
  }

  return(
    <div>
      <Prompt when={isDataChanged} 
              message={()=>"There are Some Unsaved Changes. Do you want to go Away?"}></Prompt>
      <h2>Welcome to Edit Profile...</h2>
      <p>
        <label>First Name : <input type="text" name="firstName" 
        onChange={onUserDataChange}
         value={userInfo.firstName}></input></label>
      </p>
      <p>
        <label>Last Name : <input type="text" name="lastName" 
        onChange={onUserDataChange} value={userInfo.lastName}></input></label>
      </p>
      <p>
        <label>User Name : <input type="text" name="userName" 
        onChange={onUserDataChange}
         value={userInfo.userName}></input></label>
      </p>
      <p>
        <label>Email ID : <input type="text" name="emailId" 
        onChange={onUserDataChange}
         value={userInfo.emailId}></input></label>
      </p>
      <p>
        <label>Contact Number : <input type="text" name="contactNo" 
        onChange={onUserDataChange}
         value={userInfo.contactNo}></input></label>
      </p>
      <button onClick={saveChanges}>Save</button>
    </div>
  );
}



function App(){
  return(
    <div>
      <h2>Welcome to App Component...</h2>
      <Link to="/">LogIn</Link>&nbsp;&nbsp;
      <NavLink to="/home" activeClassName="testClass">Home</NavLink>&nbsp;&nbsp;
      <NavLink to="/editprofile" activeClassName="testClass">Edit Profile</NavLink>
      
      <Switch>
        <Route exact path="/" component={LogIn}></Route>
        <SecuredRoute  path="/home" component={Home}></SecuredRoute>
        <SecuredRoute  path="/editprofile" component={EditProfile}></SecuredRoute>
      </Switch>
      
    </div>
  )
}

ReactDOM.render(<BrowserRouter><App></App></BrowserRouter>,
  document.getElementById("root"));




© 2020 Pragimtech. All Rights Reserved.