1

I am working on a react web app add want to preventDefault back button to my function in react function

for exact code use check -https://github.com/rishabhjainfinal/react-expence-calculator/blob/main/src/App.js

yes I can use react routing but I wanna test this way first

function App() {
    
     function onBack(){
        if (CP === "Month"){
            UpdateCP("Year")
        }
        else if (CP === "Day"){
            UpdateCP("Month")
        }        
    }    
    
    //some event listener function to prevent to go back 

    switch (CP){
        case 'Day':
            return (<Day date={AD} CP={CP} UpdateCP={UpdateCP}/>)
        case 'Year':
            return (<Year monthNames={monthNames} CP={CP} UpdateCP={UpdateCP} UpdateAM={UpdateAM} Save_in_excel={Save_in_excel}/>)
        default :
            return (<Month month={AM} CP={CP} UpdateCP={UpdateCP} UpdateAD={UpdateAD} AM={AM} AY={AY} monthNames={monthNames} />)
    }
}

This is my first react app and want to do it this way only.

Yes, there are many different ways but none of then is working:

the more detailed description -> supposed you created a react P.W.App of single-page but you wanna change the components every time back button is pressed like mobile back button or browser back button, and this is only possible by listening to the press of the back-button and prevent default case and run my own function this takes 2 steps:-

  1. listen to the event
  2. run function

try using

const [finishStatus, setfinishStatus] = useState(false);

    useEffect(() => {
        const onBackButtonEvent = (e) => {
            console.log('kdfjlsdjfds')
            e.preventDefault();
            if (!finishStatus) {
                if (window.confirm("Do you want to go back ?")) {
                    setfinishStatus(true)
                    // your logic
                    // props.history.push("/");
                } else {
                    window.history.pushState(null, null, window.location.pathname);
                    setfinishStatus(false)
                }
            }
        }
    
        window.history.pushState(null, null, window.location.pathname);
        window.addEventListener('popstate', onBackButtonEvent);
        return () => {
            window.removeEventListener('popstate', onBackButtonEvent);  
        };
    });

this code does nothing in my app (no effect at all) for of componentDidMount and componentDidUnMount in useEffect hook, our whole page is a single component when it Unmounts page unloads

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
Rishabh Jain
  • 19
  • 1
  • 8
  • stuck on this for some time, please help – Rishabh Jain Dec 30 '20 at 00:39
  • 1
    What exactly is the issue, or rather, what is your question? Can you provide a more [Minimal, ***Complete***, and ***Reproducible***](https://stackoverflow.com/help/minimal-reproducible-example) code example that demonstrates your attempt to prevent back navigation and execute *some* function? Provide what your actual result is versus what your expected result should be? Details about any issues and what debugging steps you've taken and include the steps to reproduce it? – Drew Reese Dec 30 '20 at 04:11
  • @DrewReese I edit the question may this will { clear the problem,? : just enter a new comment } – Rishabh Jain Dec 30 '20 at 12:57

1 Answers1

1

I still don't see where you try to prevent any back navigation, but you can use history.block from the router context. When a "POP" action is initiated you can run your custom logic to allow or block the route transition from occurring.

The following is an example usage:

const history = useHistory();

useEffect(() => {
  const unblock = history.block((location, action) => {
    if (action === "POP") {
      // Return true to allow transition, false to block
      return window.confirm("Navigate Back?");
    }
  });

  return () => {
    unblock();
  };
}, []);

Edit listen-to-back-button-in-mobile-browser-and-e-preventdefault-then-use-our-sepa

Full example code:

const TestComponent = () => {
  const history = useHistory();

  React.useEffect(() => {
    const unblock = history.block((location, action) => {
      if (action === "POP") {
        return window.confirm("Navigate Back?");
      }
    });

    return () => {
      unblock();
    };
  }, []);

  return (
    <div>
      <h3>Test Page</h3>
      <div>
        <p>Try navigating away</p>
      </div>
    </div>
  );
};

function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <Router>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/test">Test</Link>
          </li>
          <li>
            <Link to="/other">Other</Link>
          </li>
        </ul>

        <Switch>
          <Route path="/test">
            <TestComponent />
          </Route>
          <Route path="/other">
            <div>
              <h3>Some Other Page</h3>
              <div>
                <p>This is some other page</p>
              </div>
            </div>
          </Route>
          <Route>
            <div>
              <h3>Home Page</h3>
              <div>
                <p>This is the home page</p>
              </div>
            </div>
          </Route>
        </Switch>
      </Router>
    </div>
  );
}

Using window.beforeunload

Here is a fairly trivial example for how to use window.beforeunload.

React.useEffect(() => {
  const callback = (e) => {
    if (blockingCondition) {
      e.preventDefault();
      e.returnValue = "";
    }
  };

  window.addEventListener("beforeunload", callback);

  return () => window.removeEventListener("beforeunload", callback);
}, [blockingCondition]);

Edit listen-to-back-button-in-mobile-browser-and-e-preventdefault-then-use-our-sepa (forked)

Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • this is for the case of routing components as according to my need I am using a single component to render multiple components and the problem is -> like user use the web app as this 1st google, 2nd my app. now when the user tried to go back from 2nd to 1st then the custom function will call to stop going back from some logic ,thanks for your help so far looking forward to some more. – Rishabh Jain Dec 31 '20 at 02:39
  • I hope this makes some sense now – Rishabh Jain Dec 31 '20 at 02:41
  • @RishabhJain Do you mean something like [window.beforeunload](https://stackoverflow.com/a/64967211/8690857)? If that doesn't quite go far enough but is along the correct path I can tailor an answer for you. – Drew Reese Dec 31 '20 at 03:37
  • sorry no idea, because I am still learning this, but thanks for all your tries and support – Rishabh Jain Dec 31 '20 at 04:01
  • @RishabhJain So can you confirm that I understand your use-case? You've an app and a user navigates from *any* URL to *your app's* URL and your app loads. *Then*, later the user clicks/presses a back button to navigate from your app's URL back to the *any* URL. You want to capture and possibly prevent this back navigation? If this is correct then I think `window.beforeunload` is what you are looking for. – Drew Reese Dec 31 '20 at 04:31
  • ya, but how can I implement this in react application – Rishabh Jain Dec 31 '20 at 18:06
  • @RishabhJain Updated my answer with a trivial example and linked codesandbox. Give it try. – Drew Reese Dec 31 '20 at 23:14
  • this way we can prevent a user from reloading or navigating to different sites but not from going back to google if the user opens the page from google, just confirm it from your code - open the codesandbox page link to a new tab then you will notice this issue – Rishabh Jain Dec 31 '20 at 23:22
  • can I contact you someway Instagram, WhatsApp, discord for a better explanation and sharing data my reputation on SO is not enough for chatbox – Rishabh Jain Dec 31 '20 at 23:31
  • It's rather difficult to demo the back navigation blocking in the CSB, but if you copy the URL, open a browser window to google.com, then paste the CSB URL to navigate there, then try to navigate back to google, it should block. I would say SO chat would be sufficient, but it doesn't appear you've enough rep yet. If this conversation offers it though let's do that. – Drew Reese Dec 31 '20 at 23:37
  • **paste the CSB URL to navigate there, then try to navigate back to google** done that not working for me, going with routing this approach seams dead end - if you are interested in [discord chat](https://discord.gg/Tedb2McJ) expire in 1 day. – Rishabh Jain Dec 31 '20 at 23:55
  • @RishabhJain I tested and verified it works in Chrome before sharing with you. You may need to click *in* the iframe of CSB where the app is running. Like I said, it's a little tricky in CSB since the code runs in an iframe. – Drew Reese Dec 31 '20 at 23:58
  • Also, sometimes there isn't a one-size-fits-all solution, occasionally you may need to implement multiple methods to handle edge-cases. – Drew Reese Jan 01 '21 at 00:05