Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interactivity API page restoring breaks embedded SPA apps with routing #60455

Open
esamattis opened this issue Apr 4, 2024 · 2 comments
Open
Labels
[Feature] Interactivity API API to add frontend interactivity to blocks. [Type] Bug An existing feature does not function as intended

Comments

@esamattis
Copy link

esamattis commented Apr 4, 2024

Description

Interactivity API forces a page reload when it sees an unknown page for its pages cache in the popstate event.

The relevant code is here

// Listen to the back and forward buttons and restore the page if it's in the
// cache.
window.addEventListener( 'popstate', async () => {
const pagePath = getPagePath( window.location ); // Remove hash.
const page = pages.has( pagePath ) && ( await pages.get( pagePath ) );
if ( page ) {
renderRegions( page );
// Update the URL in the state.
state.url = window.location.href;
} else {
window.location.reload();
}
} );

This unfortunately breaks navigation in many single-page apps embedded in WordPress that use routers which manipulate the URL using the browser History API. For example search views commonly save the search filters to the query string using it. This happens for example with React and React Router when using the BrowserRouter. But I believe this affects any framework using the History API (Vue, Svelte, Solid, Angular etc.) and any manual History API usage.

This is unfortunate because it discards any state the SPA app might have. Like text typed in a textarea etc.

Not sure how this should be fixed. Maybe a hook which could be used to prevent the reloads on certain cases. For example we could store a flag to history.state and skip the reload based on that.

Step-by-step reproduction instructions

  1. Go to any WordPress site with the Interactivity API
  2. Open devtools and type history.pushState({}, "", "?ding=dong");
  3. Press the browser back button
  4. Press the browser forward button

The browser unexpectedly reloads the page because an url with ?ding=dong is emitted from the popstate event which is not in the pages cache.

Screenshots, screen recording, code snippet

No response

Environment info

Using WordPress 6.4.2 and Gutenberg bundled with it. This affects any newer versions as well because the same code is in trunk.

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@esamattis esamattis added the [Type] Bug An existing feature does not function as intended label Apr 4, 2024
@juanfra juanfra added the [Feature] Interactivity API API to add frontend interactivity to blocks. label Apr 4, 2024
@luisherranz
Copy link
Member

It makes sense to fix this.

@DAreRodz we could include a state object in the push/replace to signal that the navigation was made with the Interactivity API.

@DAreRodz
Copy link
Contributor

DAreRodz commented Jul 2, 2024

We could include a state object in the push/replace to signal that the navigation was made with the Interactivity API.

Yes, I agree it makes sense. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Interactivity API API to add frontend interactivity to blocks. [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

No branches or pull requests

4 participants