skip to Main Content

I am creating a react-router prompt, so here I want to apply the alert message when you want to switch from one tab to another. I have applied the alert property for that I had create a function confirmSwitchTab, but it’s not working. How do I make that prompt so that when I want to switch from one tab to another in every route, it shows the message.

import { React, useState } from "react";
import { Link } from "react-router-dom";
import LoadingBar from "react-top-loading-bar";
import { useNavigate } from "react-router-dom";

export default function Demo() {
  const [progress, setProgress] = useState(0);
  const navigate = useNavigate();

  function confirmSwitchTab() {
    //Prompt the user with a confirm message.
    var result = confirm("Are you sure you want to switch tabs?");
    //If the user confirms, return true, else return false.
    if (result) {
      return true;
    } else {
      return false;
    }
  }

  const onClick = () => {
    const userConfirmsSwith = confirmSwitchTab()
    if (userConfirmsSwith) navigate("/")
    // else you don't do anything.
  }

  return (
    <>
      <LoadingBar
        color="blue"
        progress={progress}
        onLoaderFinished={() => setProgress(0)}
        waitingTime={800}
        loaderSpeed={100}
        height={4}
      />
      <ul
        style={{
          display: "flex",
          justifyContent: "space-around",
          listStyle: "none"
        }}
      >
        <li>
          <Link
            to="/"
            onClick={() => {
              onClick();
              setTimeout(() => setProgress(100), 500)
            }}
          >
            Home
          </Link>
        </li>
        <li>
          <Link
            to="/about"
            onClick={() => {
              onClick();
              setTimeout(() => setProgress(100), 500)
            }}
          >
            About
          </Link>
        </li>
      </ul>
    </>
  );
}

2

Answers


  1. I believe there has been a misunderstanding on how onLeave works here 🙂

    returning true is not going to "confirm the leave action". The leave action is confirmed no matter what. The onLeave prop will simple take a function and fire it when you leave the page. This function can be a prompt, like here, but the returned value won’t be used.

    What you are trying to achieve has to be done before the actual leave of the page. Somewhere in your app, you should have a navigation menu in which you actually make the page change on the button click (typically with

    history.push("My/New/Path")
    

    )

    now that is where you want to use your function.

    let’s say you have something like

    <Button onClick={history.push('home')} >Home</Button>
    

    You want to call your confirmSwitchTab function in that callback.

    you could change it into something like

    const onClick = () => {
      const userConfirmsSwith = confirmSwitchTab()
      if (userConfirmsSwith) history.push('home')
      // else you don't do anything.
    }
    <Button onClick={onClick}>Home</Button>
    

    hope this helped, let me know if I got the problem wrong!

    cheers

    After question edition

    try this:

    import { React, useState } from "react";
    import LoadingBar from "react-top-loading-bar";
    import { useNavigate } from "react-router-dom";
    export default function Demo() {
      const [progress, setProgress] = useState(0);
      const navigate = useNavigate();
      function confirmSwitchTab() {
        //Prompt the user with a confirm message.
        var result = confirm("Are you sure you want to switch tabs?");
        //If the user confirms, return true, else return false.
        if (result) {
          return true;
        } else {
          return false;
        }
      }
      const onClick = (path) => {
        setTimeout(() => setProgress(100), 500)
        const userConfirmsSwith = confirmSwitchTab()
        if (userConfirmsSwith) navigate(path)
        // else you don't do anything.
      }
      return (
        <>
          <LoadingBar
            color="blue"
            progress={progress}
            onLoaderFinished={() => setProgress(0)}
            waitingTime={800}
            loaderSpeed={100}
            height={4}
          />
          <ul
            style={{
              display: "flex",
              justifyContent: "space-around",
              listStyle: "none"
            }}
          >
            <li>
              <Button onClick={() => {onClick("/")}>
                Home
              </Button>
            </li>
            <li>
              <Button onClick={() => {onClick("/about")}>
                About
              </Button>
            </li>
          </ul>
        </>
      );
    }
    
    Login or Signup to reply.
  2. It is not working because the code isn’t preventing the default link action from occurring. The link is clicked and the navigation action is effected immediately, while at the same time the attached onClick handler is running other logic.

    The click handler should consume also the click event object and call preventDefault on it to stop the navigation action from ocurring.

    export default function Demo() {
      const [progress, setProgress] = useState(0);
      const navigate = useNavigate();
    
      function confirmSwitchTab() {
        //Prompt the user with a confirm message.
        return confirm("Are you sure you want to switch tabs?");
      }
    
      const clickHandler = (target = "/") => (e) => {
        e.preventDefault(); // <-- halt link navigation
    
        setTimeout(() => setProgress(100), 500);
    
        if (confirmSwitchTab()) {
          navigate(target);
        }
        // else you don't do anything.
      }
    
      return (
        <>
          <LoadingBar ... />
          <ul ... >
            <li>
              <Link to="/" onClick={clickHandler("/")}>
                Home
              </Link>
            </li>
            <li>
              <Link to="/about" onClick={clickHandler("/about")}>
                About
              </Link>
            </li>
          </ul>
        </>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search