question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Difficult to migrate .block() use case to v5

See original GitHub issue

Hi,

I use history.block to check whether the next location can be transition to. If not, do a full page load. The pseudo code looks like

const unblock = history.block((tx) => {
  // canTransition is the function that checks if next location can be SPA transition to
  // If false, do a full page load on next location's path
  if (!canTransition()) {
    return window.location.assign(nextPath);
  }
  unblock();
  tx.retry();
});

Full code example: https://codesandbox.io/s/distracted-river-8yczz?file=/src/index.js

So depending on the result of canTransition(), it should either unblock the blocker or do a full page reload. Users shouldn’t notice much difference. This is fine except for the navigation that reloads the page. Users see something like this (Chrome): image It doesn’t make sense to our users as there isn’t any unsaved changes. I’ve read the documentation and understand the library registers a beforeunload handler to prevent the navigation. Maybe v5’s .block is not designed for my use case.

But I am able to achieve this use case via history v4. I’ve also tried history.listen but .listen is too late as it happens at the end of applyTx.

Any suggestion is much appreciated. 🙂 The solution I can think of is to remove window.addEventListener(BeforeUnloadEventType, promptBeforeUnload); from the library and let consumer of the library to handle it.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:3
  • Comments:5

github_iconTop GitHub Comments

3reactions
liamqmacommented, Jan 7, 2022

I’ve found a hacky workaround 😬

window.addEventListener('beforeunload', () => {
        unBlock();
});

Register our own BeforeUnloadEvent and clean up our transition blockers before history runs its check

2reactions
dubzzzcommented, Feb 3, 2022

@liamqma Thank you so much for the workaround it works perfectly well in my case too. I just had to register my own event listener before calling block which I did the other way initially.

Meanwhile I am wondering if calling the provided blockers on “beforeunload” could be something directly implemented inside history itself. I came up with this code on my side (highly inspired from react-router beta.6):

// location being undefined when beforeunload cases
export type BlockerFunction = (tx: { location: Location | undefined; retry: () => void }) => void;

export function useBlocker(blocker: BlockerFunction): void {
  const navigationContext = useContext(UNSAFE_NavigationContext);
  const navigator = navigationContext.navigator as History;

  useEffect(() => {
    const beforeUnloadCallback = () => {
      let closeAuthorized = false;
      blocker({
        location: undefined,
        retry: () => {
          closeAuthorized = true;
        },
      });
      if (closeAuthorized) {
        unblock();
      }
    };
    window.addEventListener('beforeunload', beforeUnloadCallback);

    const unblock = navigator.block((tx) => {
      const autoUnblockingTx = {
        ...tx,
        retry() {
          unblock();
          tx.retry();
        },
      };
      blocker(autoUnblockingTx);
    });

    return () => {
      unblock();
      window.removeEventListener('beforeunload', beforeUnloadCallback);
    };
  }, [block, blocker]);
}

The beforeUnloadCallback is basically doing the trick you talked about plus calling the underlying blocker to check whether or not we should prevent the default behaviour of the browser. If we should, then we let the beforeunload handler registered by history do the blocking, otherwise we unplug it (your code).

I’m wondering if such behaviour should be the default for block in history. It would made users able to say whether or not they really want to lock the tab closing. Is there a reason not to call blockers when receiving things on beforeunload?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Breaking changes in v5, part two: core components - Material UI
This is a reference guide to all of the breaking changes introduced in Material v5, and how to handle them when migrating from...
Read more >
Optimise representation of deeply-nested StreamField blocks ...
Here's an example. This one model's migration code is nearly 500,000 characters. And another half megabyte of text will be repeated in each ......
Read more >
5 Key Steps to Successfully Migrate From Hadoop to the ...
Learn about the key steps to keep in mind for a successful migration off Hadoop and the role the lakehouse architecture plays in...
Read more >
Database migration: Concepts and principles (Part 1)
This special case uses the database migration system for data transformation only, not for migrating data between different systems across ...
Read more >
Migrating a microservice to Spring WebFlux - allegro.tech blog
block() can be used only in code executed under scheduler. Even better is to avoid using .block() at all. Issue 5 - blocking...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found