Instantsearch.js: urlSync + Turbolinks back button not working

Created on 21 Apr 2016  路  17Comments  路  Source: algolia/instantsearch.js

I am using the using instantsearch with turbolinks and am experiencing an issue where the back button is not working correctly.

My search coffeescript

search = instantsearch(
      appId: 'id'
      apiKey: 'key'
      indexName: 'index'
      urlSync: {
        threshold: 300
      })

When I search products, the url is updated as expected, search works. If I click on a product, than click the back button, the url changes to the previously generated search url, but I stay on the product#show page for the instance I was viewing. Clicking back button a second time takes me to the root /products page.

This issue doesn't occur when setting useHash: true, unfortunately analytics team needs this to be query params.

Most helpful comment

All 17 comments

Can you point us to a live example of the bug you are experiencing?

Maybe build a simple reduced test case using turbolinks + instantsearch.js to demonstrate the problem?

That would help us, thanks

Sorry @vvo, it looks like you fixed with @kle-roy, but I am still experiencing the same issue, so I am trying to figure out what I am missing. I updated my instantsearch.min.js to 1.4.5. Does it look like I am passing the new setting correctly when instantiating? Thanks.

   search = instantsearch(
      appId: 'id'
      apiKey: 'key'
      indexName: 'products'
      urlSync: {
        threshold: 300
        useHash: false
        getHistoryState: ->
          { turbolinks: true }
      }) 

@ThomasBush : as mentioned by @vvo on #992, the getHistoryState feature is not released yet ; for now, you can just test it on the develop branch

Ah thanks, sorry, I missed that last bit.

Hi @vvo do you have an example of how to achieve Turbolinks compatibility with the new router option?

Seems like we need to add { turbolinks: true } as the first argument of history.replaceState in routing if that's the case cc @bobylito

@Spone, can you try:

instantsearch({
  routing: {
    stateMapping: {
      stateToRoute(uiState) {
        return {
          turbolinks: true,
          ... uiState,
        };
      },
      routeToState({turbolinks, ...routeState}) {
        return routeState
      }
    }
  }
});

I can't try this because I don' have a reproduction

@Haroenv it seems to work perfectly! Thanks

@Haroenv amazing :) Seems like a good thing to add into a migration guide (maybe the one for preparing v3?)

Yes, or maybe we could make it an option to add this by default?

Yes, or maybe we could make it an option to add this by default?

It's a rather specific use case and the fix is very small, I don't know if there is a strong benefit to have an option 馃

But turbolinks=true appears in the URL query string when I do that. Can I hide it?

Also, it would be great to have at least a few lines of documentation about this turbolinks options. It seems to be black magic :D

Also, it would be great to have at least a few lines of documentation about this turbolinks options. It seems to be black magic :D

Yes totally, especially since it was an option of the urlSync. From what I can read about turbolinks, the project is very much black magic 馃槄

But turbolinks=true appears in the URL query string when I do that. Can I hide it?

I'm not quite sure how turbolinks works in practice. I don't know if you store the attribute in the history data would it still work. Could you try to remove the turboLinks attribute from the URL using a custom createURL function https://community.algolia.com/instantsearch.js/v2/guides/routing.html#historyopts?

If I remove the turbolinks option like that:

import historyRouter from 'instantsearch.js/es/lib/routers/history.js';

// [...]

      router: historyRouter({
        createURL: ({ qsModule, routeState, location }) => {
          delete routeState.turbolinks; // <<<< HERE
          const { protocol, hostname, port = '', pathname, hash } = location;
          const queryString = qsModule.stringify(routeState);
          const portWithPrefix = port === '' ? '' : `:${port}`;
          if (!routeState || Object.keys(routeState).length === 0)
            return `${protocol}//${hostname}${portWithPrefix}${pathname}${hash}`;
          else
        return `${protocol}//${hostname}${portWithPrefix}${pathname}?${queryString}${hash}`;
        }
      }),

... it doesn't appear in the URL but it breaks the Turbolinks behavior (as if the option was not defined).

To be clear: what breaks is that if I click on a hit, I cannot go back to the search results with one click on the back button.

To be clear: what breaks is that if I click on a hit, I cannot go back to the search results with one click on the back button.

Ok. Do you have an error? Maybe the problem is that the default parseURL function can't parse it back.

Nope, no error, just behaving as if the turbolinks=true option was not enabled.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

object505 picture object505  路  4Comments

zeke picture zeke  路  3Comments

samouss picture samouss  路  3Comments

ChristopherDosin picture ChristopherDosin  路  4Comments

francoischalifour picture francoischalifour  路  3Comments