When working with Single Page Application, it's important to know how works the history
and location
objects to do routing.
Then in a next article we will implement a routing library in React
, react-router
like.
The History
API
The browser history is the list of all visited pages. It allows us to navigate through the history of our tab by going back to previous visited page or forward to the next visited page.
You can access to the history
object thanks to the window
with window.history
.
The properties and methods exposed by the History
API are the following ones:
length
history.length
returns the number of pages that you have visited for the current tab.
scrollRestoration
It defines the behavior after a reload of the current page. There is 2 values possible:
-
auto
: if the user has scrolled, then after reloading the page, the page will automatically scroll where the user was before. -
manual
: after reloading the current page, the user will be at the top of the page wherever the user was on the page before.
state
An history state is a sort of context in which you can store any values (that can be serialized) that needs to be kept when going to the next page. Each page has its own state.
history.state
returns the state for the current page you are. This value cannot be changed.
pushState
This method allows you to push an entry in the history. It takes as parameters:
- state: the state for the new entry
- title: You can pass a string if you want to define a title for the new state. Note that, nowadays, this parameter is not used by browsers
- url: this parameter is optional, it defines the new entry url if you want to change it. You can path a relative or absolute path until you stay on the same origin. This new url will not be loaded by your browser.
If we have: After executing: We got:Example: pushState
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
history.pushState(null, null, 'Page 4');
/*
| History stack |
| ------------- |
| Page 4 | << We are now on this page
| Page 3 |
| Page 2 |
| Page 1 |
*/
replaceState
This method allows you to replace to current entry in the history. It takes the same parameter as pushState
:
- state: the state that will replace the current one
- title: you can pass a string if you want to define a title for the new state. Note that, nowadays, this parameter is not used by browsers
- url: this parameter is optional, it defines the new entry url if you want to change it. You can path a relative or absolute path until you stay on the same origin. This new url will not be loaded by your browser.
If we have: After executing: We got:Example: replaceState
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
history.replaceState(null, null, 'Page 4');
/*
| History stack |
| ------------- |
| Page 4 | << We are now on this page
| Page 2 |
| Page 1 |
*/
back
history.back()
will move you to the previous page in the history.
If we have: After executing: We got:Example: back
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
history.back()
/*
| History stack |
| ------------- |
| Page 3 |
| Page 2 | << We are now on this page
| Page 1 |
*/
forward
history.forward()
will move you to the next page in the history.
If we have: After executing: We got:Example: forward
/*
| History stack |
| ------------- |
| Page 3 |
| Page 2 | << We are currently on this page
| Page 1 |
*/
history.forward()
/*
| History stack |
| ------------- |
| Page 3 | << We are now on this page
| Page 2 |
| Page 1 |
*/
go
history.go([integer])
allows you to move in the history further than 1 step backward or forward, depending on the integer passed as parameter:
- none or 0: it will reload the current page
- < 0: it will move backward in the history (-1 will do the same thing as
history.back()
) - > 0: it will move forward in the history (1 will do the same thing as
history.forward()
)
If we have: After executing: We got:Example: go
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
history.go(-2)
/*
| History stack |
| ------------- |
| Page 3 |
| Page 2 |
| Page 1 | << We are now on this page
*/
The Location
API
Now that we have seen what can be done with the History
API, let's focused on the Location
API.
The Location
API allows us to get some information about the current URL of the page we are on thanks to the window.location
or document.location
objects.
The properties and methods exposed by the Location
API are the following ones:
Note: In the examples bellow, we are going to imagine we are on the page: https://romaintrotard.com:443/en/posts/prevent-react-rerendering?searchKey=searchvalue#when-does-a-component-render.
href
window.location.href
returns the full URL.
Note: If you set its value (or the value of
location
), it will navigate to the given URL, and load the document (contrary tohistory.pushState
orhistory.replaceState
).
In my example it will be: https://romaintrotard.com:443/en/posts/prevent-react-rerendering?searchKey=searchvalue#when-does-a-component-render
.
protocol
window.location.protocol
returns the protocol scheme of the url (http:
or https:
).
Note: The colon is included
In my example: https:
.
hostname
window.location.hostname
returns the domain of the url.
In my example: romaintrotard.com
.
port
window.location.port
returns the port number of the url.
In my example: 443
.
host
window.location.host
returns the concatenation of the hostname
+ :
+ port
.
In my example: romaintrotard.com:443
.
origin
window.location.origin
returns the concatenation of protocol
with host
.
In my example: https://romaintrotard.com:443
.
hash
window.location.hash
returns the anchor part (also named fragment) of the url (after the #
, # included).
In my example: #when-does-a-component-render
.
search
window.location.search
returns the query string part of the url (after the ?
, ? included).
In my example: ?searchKey=searchvalue
.
pathname
window.location.pathname
returns the path of the url. It's the part after the origin
part, starting by a /
, without the anchor and query string.
In my example: /en/posts/prevent-react-rerendering
.
reload()
window.location.reload()
is a method that refresh the current page.
replace()
window.location.replace(newUrl)
is a method that redirects to the newUrl (the document is loaded, contrary to history.replaceState
). It will replace the entry in the history stack.
If we have: After executing: We got:Example: replace
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
location.replace('Page 4')
/*
| History stack |
| ------------- |
| Page 4 | << We are now on this page
| Page 2 |
| Page 1 |
*/
assign()
window.location.assign(newUrl)
is a method that redirects to the new url. But, contrary to window.location.replace
it will add a new entry in the history stack.
Note: If you wonder the difference with
location.href
navigation is some security checks thatassign
does you can find on the specification.
If we have: After executing: We got:Example: assign
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
location.assign('Page 4')
/*
| History stack |
| ------------- |
| Page 4 | << We are now on this page
| Page 3 |
| Page 2 |
| Page 1 |
*/
Conclusion
I hope I didn't lost you in the explanations. The parts that are important to know for my next article about "how to make a react-router like library" are the methods replaceState
, pushState
and go
of history
. These methods allows us to make some navigation in a single page application (without reloading the document). And pathname
, search
, hash
of the location
object. It's from this values we can know where we are to show the right routes :)
Want to see more ? Follow me on Twitter or go to my Website. 🐼
Top comments (2)
Thanks for nice examples.
Thank you for your kind message :)