react-router icon indicating copy to clipboard operation
react-router copied to clipboard

[Bug]: useBlocker is not working

Open bsrinath4839 opened this issue 1 year ago • 4 comments

What version of React Router are you using?

"react-router-dom": "^6.22.3",

Steps to Reproduce

Create some routes with createBrowserRouter().

Create a Modal which shows something.

Example code

import React from "react";
import types, { MODAL_VARIANTS } from "./modal-types";
import styles from "./modal.module.scss";
import { useDispatch } from "react-redux";
import { CHANGE_MODAL_STATE } from "../../redux/reducers/alerts.reducer";
import { useBlocker, useLocation } from "react-router-dom";

const Modal = ({ show, type, variant = MODAL_VARIANTS.PRIMARY, ...rest }) => {
  const Component = types[type];
  const dispatch = useDispatch();
  const location = useLocation();
  const [pathName, setPathName] = React.useState("");
  const whenToBlock = () => show;
  let blocker = useBlocker(whenToBlock);

  React.useEffect(() => {
    if (location.pathname !== pathName) {
      dispatch(CHANGE_MODAL_STATE({ show: false, type: null }));
    }
  }, [location.pathname, dispatch, pathName]);

  React.useEffect(() => {
    if (show) {
      setPathName(location.pathname);
    }
  }, [show, location.pathname]);

  if (show) {
    return (
      <div className={styles[variant]}>
        <div
          className={styles[`${variant}-modal-backdrop`]}
          onClick={() => {
            dispatch(CHANGE_MODAL_STATE({ show: false, type: null }));
            console.log("blocker", blocker);
            blocker.proceed();
          }}
        />

        <div className={styles[`${variant}-container`]}>
          <Component {...rest} />
        </div>
      </div>
    );
  }
  return null;
};

export default Modal;```



### Expected Behavior

When the show is false, the blocker should allow user to proceed. 

### Actual Behavior

Throwing
Uncaught TypeError: blocker.proceed is not a function
when I close the modal by using this code

onClick={() => { dispatch(CHANGE_MODAL_STATE({ show: false, type: null })); console.log("blocker", blocker); blocker.proceed(); }}

         
The following is coming from console.log

{ location: undefined proceed: undefined reset: undefined state: "unblocked" }

bsrinath4839 avatar Mar 29 '24 09:03 bsrinath4839

You may have a stale closure problem - try using the value directly or using a callback with dependencies:

// Direct
let blocker = useBlocker(show);

// Callback
const whenToBlock = React.useCallback(() => show, [show]);
let blocker = useBlocker(whenToBlock);

Or, you my need to wait for the react state to flush out after dispatching your action. It's hard to say without a working reproduction.

brophdawg11 avatar Mar 29 '24 14:03 brophdawg11

I can confirm this as well

samuelkarani avatar Apr 05 '24 13:04 samuelkarani

You may have a stale closure problem - try using the value directly or using a callback with dependencies:

// Direct
let blocker = useBlocker(show);

// Callback
const whenToBlock = React.useCallback(() => show, [show]);
let blocker = useBlocker(whenToBlock);

Or, you my need to wait for the react state to flush out after dispatching your action. It's hard to say without a working reproduction.

I don't think this is the issue. I have tried this no difference.

samuelkarani avatar Apr 05 '24 14:04 samuelkarani

Could either of you provide a minimal reproduction?

brophdawg11 avatar Apr 05 '24 18:04 brophdawg11

This issue has been automatically closed because we haven't received a response from the original author 🙈. This automation helps keep the issue tracker clean from issues that aren't actionable. Please reach out if you have more information for us! 🙂

github-actions[bot] avatar Apr 15 '24 18:04 github-actions[bot]