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

Support Hash History? #25

Closed
oferitz opened this issue Jun 1, 2018 · 31 comments
Closed

Support Hash History? #25

oferitz opened this issue Jun 1, 2018 · 31 comments

Comments

@oferitz
Copy link

oferitz commented Jun 1, 2018

In React router you can do something like this:

import createHashHistory from 'history/createHashHistory'
<Router history={history}>
 <Routes />
</Router>

Is this supported?

This is very useful in environment like Electron where you can't use the "normal" HTML5 history API.

I didn't found anything in the docs except from this: https://reach.tech/router/api/createHistory but it doesn't seems related to what i'm looking for.

@ryanflorence
Copy link
Member

No it's not.

In electron you can use a memory history instead of hash, yeah?

import {
  createMemorySource,
  createHistory,
  LocationProvider
} from "@reach/router"

let source = createMemorySource("/starting/url")
let history = createHistory(source)

let App = () => (
  <LocationProvider history={history}>
    <Router>
      {/* ... */}
    </Router>
  </LocationProvider>
)

@oferitz
Copy link
Author

oferitz commented Jun 1, 2018

Thanks.

The memory history will probably work, but would you consider a PR that add support for hash history also?

@ryanflorence
Copy link
Member

No. Hash history has a lot of edge cases that I don't want to deal with, but if you look at the source of createMemorySource you can see what you need to make a createHashSource.

@will-stone
Copy link

@oferitz I'd quite like this too. If you work on a Reach add-on to support hash history, do you mind posting it here so others may use it too?

And thanks Ryan for providing this router. It's definitely the easiest to use to-date.

@oferitz
Copy link
Author

oferitz commented Jun 16, 2018

@will-stone If i understood @ryanflorence correctly, he will not consider any PR for adding hash support. so i didn't started any work on such thing. i actually found that memory history could work on my use case (Electron).

@will-stone
Copy link

Okay, thanks @oferitz, I'll look into it myself if I get time.

@will-stone
Copy link

@oferitz I've had a go at creating my own hash source: https://github.com/will-stone/hash-source

@ryanflorence I know you said you wouldn't be officially supporting this but I'd really appreciate it if you could do a quick once-over of the code (there's not a lot there) and let me know if there's any glaring omissions, or is just not the way it should be handled. Thanks.

@nickserv
Copy link

nickserv commented Aug 5, 2018

Wow, you can use the same LocationProvider with a different history source? This looks very promising, thanks @will-stone. Please ping me when it's published or if you need any help.

@will-stone
Copy link

will-stone commented Aug 6, 2018

@NickColley it has been published: https://www.npmjs.com/package/hash-source

I've put together a sandbox to demo it: https://codesandbox.io/s/30yj1213m
However, the back/forwards functionality doesn't work on the sandbox (it did on my local tests). Which means we may need to use onHashChange. Anyway, if anybody would like to help out, please log issues/PRs on its repo and save Ryan from the noise on here.

edit: loading in separate window demonstrates it properly: https://30yj1213m.codesandbox.io/#/

@jimthedev
Copy link

Yeah @will-stone I was doing some things with hash previously and recall codesandbox not liking it.

@j3l11234
Copy link

j3l11234 commented Nov 6, 2018

I also write a lib for use reach/router with hash. and also publish it
look the similar to @will-stone .
I think the reach/router just use a little part of location api and history api, so create a hash histroy is easy. I will update it continuously
feel free to add issue

https://github.com/j3l11234/reach-router-hash-history
https://www.npmjs.com/package/reach-router-hash-history

@will-stone
Copy link

@j3l11234 Hmmm... I'm not sure how I feel about that. Does yours offer anything over mine? It looks very similar. Some comments and functions are identical! If anything is missing, I'm happy to accept PRs and issues. It's not even forked or credited in the README. I'd say you've scored badly on open source etiquette.

@raveenakothapally
Copy link

raveenakothapally commented Nov 6, 2018

@ryanflorence - I don't think createMemorySource persists state across refreshes which can be annoying during development. Would appreciate if memory is preserved across page refreshes.

FYI. This will not be a problem for hash routers or browser routers as the href on refresh won't change.

One workaround I could think of -

const REACH_ROUTER_LOCATION = "<SOME_STORAGE_KEY>";
const path = localStorage.getItem(REACH_ROUTER_LOCATION);

let source = createMemorySource(path || "/");
let history = createHistory(source);

const RootReachNode = () => (
  // You could also use a useEffect/unmount hook to capture pathname if this is not root node
  <LocationProvider history={history}>
      {...}
  </LocationProvider>
);

window.addEventListener("beforeunload", () => {
  localStorage.setItem(REACH_ROUTER_LOCATION, history.location.pathname);
});

@j3l11234
Copy link

j3l11234 commented Nov 7, 2018

@will-stone Im sorry about that,In fact, that was not my intention. you can find the previous commit. I use another way to fix it.
I want to make hash history similar to history, such as the overide addEventListener, I rewrite popstate to hashchange. I will simulate the state like history later.
I will add the credit for you and I sincerely apologize for that again.

@andreiglingeanu
Copy link

@will-stone thanks! Works fine for my use case.

@gaoxiaoliangz
Copy link

I created a forked version for my use case https://github.com/gaoxiaoliangz/router. Just add useHashRouting to the Router component and you are good to go.

@hardcoremore
Copy link

hardcoremore commented Jan 24, 2019

One rookie question though. If reach router is not using hash to prevent page reload how you supposed to keep redux state?

Isn't the idea of react to create single page web applications so that you do not have to reload everything on each page change? If we are reloading everything when changing page what is the purpose of the react than I can use jQuery as well.

@nickserv
Copy link

The HTML5 History API (specifically History.pushState()) allows you to change the URL without reloading, as if the user navigated normally. Most routing libraries including Reach Router use this to simulate navigation in SPAs without full reloads. Hash history is just an alternate URL syntax for browsers that don't support HTML5 History.

@hardcoremore
Copy link

hardcoremore commented Jan 24, 2019

Yeah, that is true. Except when user wants to change route manually than page is reloaded. For example if I am on route example.com/#home and I change url in the address bar to example.com/#report the page will not be reloaded. But if you do not use hash and change url in the address bar the page will reload.

@hardcoremore
Copy link

@will-stone Hey will, this hash history is working great, but how can I use navigate function with it?

If I use navigate it stops using hash completely and it just redirects like regular link.

@hardcoremore
Copy link

The HTML5 History API (specifically History.pushState()) allows you to change the URL without reloading, as if the user navigated normally. Most routing libraries including Reach Router use this to simulate navigation in SPAs without full reloads. Hash history is just an alternate URL syntax for browsers that don't support HTML5 History.

But everytime I use navigate function or Link component the page reloads completely and all state of the app is lost. How can I prevent this (without using hash history) ?

@will-stone
Copy link

Hi @hardcoremore, thanks for the praise. Do you mind raising any issues you have with hash-source on the repo itself? If you include a codesandbox/demo-repo that would greatly help with debugging the issue.

@hardcoremore
Copy link

Hi will, yes I will open the ticket on the repo.

Thanks

@lsps9150414
Copy link

@hardcoremore Hi, have you found the solution to this? It will be a great help if you could share your findings, thanks!

But everytime I use navigate function or Link component the page reloads completely and all state of the app is lost. How can I prevent this (without using hash history) ?

@Akiyamka
Copy link

Akiyamka commented Aug 29, 2019

@nickmccurdy

Hash history is just an alternate URL syntax for browsers that don't support HTML5 History.

You are not right, there is a huge difference between them. In case we have link without hash (some.site/about/ for example) after page refresh or reopen tab, or if you share that link - browser create GET request to some.site/about/index.html. By default static server return 404 error on this request because entry point with js who handle routing located in some.site/index.html.

Of course it can be fixed after some back-end reconfiguration for redirect requests, however, we have many cases when we do not have access to do this (surge.sh, github pages, netlify, etc.)

Hash routing does not require any additional configuration to work because some.site/#/about/ create correct request to some.site/index.html

@Akiyamka
Copy link

Akiyamka commented Aug 30, 2019

@j3l11234 thx, your package help me

@emilioplatzer
Copy link

Most HTML5 Offline applications needs hash route, because you must list all of your paths in the app.manifest resource.

@asktree
Copy link

asktree commented Sep 11, 2019

I am in the situation that @Akiyamka outlines; I use static hosting, need my users to be able to open mysite.com/img/[image_id] in a new tab, and there's no way to do this AFAIK without using react-router or SSRing all 1m of my images.

@nickserv
Copy link

Please consider making it easier to use this, I use GitHub Pages on all my open source project sites and it's significantly more difficult to set up Reach Router with hash routing than to use another router that supports it, but I need Reach Router's accessibility features

@prionkor
Copy link

prionkor commented Aug 9, 2020

I tried to use solutions provided here and as well as the package reach-router-hash-history. I couldn't use navigate() function because state wasn't propagated with the hash history.

I have rewrite hash history code and made a gist that fixes the problem. I am putting it here if anybody needs it.

https://gist.github.com/prionkor/59215ff78de7b706fbb6b97a9a61b578

@nickserv
Copy link

FYI almost a year has passed since my last comment. From what I remember, Reach Router's development has slowed down and new features will likely not be added. Instead, it's recommended to migrate to React Router 6, which is based on some of the API improvements of Reach Router. It also has a HashRouter component built in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests