NourAlzway / use-router-with-events

React custom hook for Next.js's useRouter
https://www.npmjs.com/package/use-router-with-events
MIT License
14 stars 0 forks source link

Would this work for preventing navigation if a form has unsaved changes? #3

Open simon-marcus opened 2 months ago

simon-marcus commented 2 months ago

Hi! Your package like a great solution to a bothersome problem in the new App router. I'm specifically trying to intercept events before navigation to prevent users from navigating away from a form if the user has unsaved changes. Would this work?

spacecat commented 2 months ago

Wondering this as well.

NourAlzway commented 1 week ago

Hi @simon-marcus (cc: @spacecat)

Thank you for your interest in use-router-with-events. Yes, you can absolutely use it to intercept navigation events and prevent users from leaving a page with unsaved changes. This functionality can help you show a confirmation modal or prompt the user before they navigate away, which is especially useful in cases like unsaved forms.

Here’s an example of how to handle this:

"use client";
import useRouterWithEvents from "use-router-with-events";
import { useState, useEffect } from "react";

const ContactPage = () => {
  const [isFormDirty, setIsFormDirty] = useState(false);
  const router = useRouterWithEvents();

  useEffect(() => {
    // Define the function to intercept the route start event
    const handleRouteStart = () => {
      if (isFormDirty) {
        return confirm("You have unsaved changes. Are you sure you want to leave?");
      }
      return true;
    };

    // Register the event handler when the component mounts
    router.events.onRouteStart = handleRouteStart;

    // Cleanup the event handler when the component unmounts
    return () => {
      router.events.onRouteStart = null;
    };
  }, [isFormDirty, router.events]); // Dependencies to update the listener when form state changes

  const handleInputChange = () => {
    setIsFormDirty(true); // Mark form as dirty when input changes
  };

  const handleSave = () => {
    // Logic to save form data
    setIsFormDirty(false); // Reset dirty state after saving
    alert("Form saved!");
  };

  const handleClick = () => {
    // Navigate to the home page
    router.push("/");
  };

  return (
    <div>
      <h1>Contact Form</h1>
      <form>
        <label>
          Name:
          <input type="text" onChange={handleInputChange} />
        </label>
        <label>
          Email:
          <input type="email" onChange={handleInputChange} />
        </label>
      </form>
      <button onClick={handleSave}>Save</button>
      <button onClick={handleClick}>Return to Home</button>
    </div>
  );
};

export default ContactPage;

Explanation

This should allow you to intercept navigation events and prompt the user if they attempt to leave with unsaved changes.

Let us know if you have any questions or need further customization!

Best regards, Nour

spacecat commented 1 week ago

Thanks for the info. Just wanted to add that in my case I have links in my layouts and this means regular Link components will not work unless you wrap them in your own component with additional functionality.