skip to Main Content

When upgrading to React-Router 6 due to some custom architecture around routing and Redux and React-Router removing the Prompt component I had to go with my custom blocking module that was based on history package. I created it within useEffect call as below:

useEffect(() => {
  if (shouldBlock) {
    const unblock = history.block(transition => {
      const url = transition.location.pathname;
      openPromptDialog(url, unblock);
    });
  }
}, [shouldBlock]);

Everything looked like it’s working but I found some minor bug. The openPromptDialog opens a custom confirm dialog when we want to leave a page with a dirty form (shouldBlock is true). This part works, but it does not when on the page we save the form and the want to leave. The form is no longer dirty so shouldBlock is false however since it used to be true we didn’t have a chance to unblock it and I can’t find a way to do it.

Please note that I don’t wanna rely on React-Router blocking since I don’t (and can’t at the moment) use Data API createBrowserRouter which is required in to use useBlocker.

2

Answers


  1. You can try this to unblock variable is declared outside the if (shouldBlock) block and is accessible in the cleanup function. When the component is unmounted or when shouldBlock changes, the cleanup function will be executed, and it will call unblock if it exists. This ensures that the blocking is properly removed even if shouldBlock becomes false.

    useEffect(() => {
      let unblock;
    
      if (shouldBlock) {
        unblock = history.block(transition => {
          const url = transition.location.pathname;
          openPromptDialog(url, () => {
            unblock();
          });
        });
      }
    
      return () => {
        if (unblock) {
          unblock(); 
        }
      };
    }, [shouldBlock]);
    
    Login or Signup to reply.
  2. The code you have doesn’t ever unblock navigation actions once shouldBlock is set true, e.g. like after it is toggled back to false.

    You can return a cleanup function to unblock navigation actions when the shouldBlock dependency updates. This will clean up any previous blockers.

    Example:

    useEffect(() => {
      if (shouldBlock) {
        const unblock = history.block(transition => {
          const url = transition.location.pathname;
          openPromptDialog(url, unblock);
        });
    
        return unblock; // <-- unblock as cleanup function when set
      }
    }, [shouldBlock]);
    

    Demo

    Edit unblock-react-history-push-on-particular-condition

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search