I am creating a react-router
alert, so here I want to apply an alert message when you want to switch from one tab to another. I've applied the alert attribute because I created a function confirmSwitchTab
but it doesn't work. How can I make that prompt so that when I want to switch from one tab to another in each route, it displays 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> </> ); }
P粉5643017822024-02-04 15:50:08
It doesn't work because the code doesn't prevent the default link action from happening. When a link is clicked, the navigation action takes effect immediately while the attached onClick
handler is running other logic.
Click handlers should also consume the click event object and call preventDefault
on it to stop navigation operations from occurring.
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 ( <>
P粉9147310662024-02-04 12:11:39
I believe there is a misunderstanding here about how onLeave works :-)
Returning true will not "confirm the leave operation". Regardless, the request for leave will be confirmed. The onLeave attribute will simply take a function and trigger it when you leave the page. This function can be a hint, like here, but the returned value will not be used.
What you want to achieve must be completed before the page actually leaves. Somewhere in your application you should have a navigation menu where you can actually change pages by clicking a button (usually using
history.push("My/New/Path")
)
Now this is where you will use the function.
Assuming you have something similar
You want to call the confirmSwitchTab function in this callback.
You can change it to something like
const onClick = () => {
const userConfirmsSwith = confirmSwitchTab()
if (userConfirmsSwith) history.push('home')
// else you don't do anything.
}
Hope this helps, please let me know if my question is wrong!
cheers
After editing the question
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 (
<>
setProgress(0)}
waitingTime={800}
loaderSpeed={100}
height={4}
/>
-
-
>
);
}