Let's explore javascript's Location and History API
Tags: javascript, tutorial, beginners, programming
Published: 2021-08-04 13:11:05

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. 

{% collapsible Example: pushState  %}

If we have:

```javascript
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
```

After executing:

```javascript
history.pushState(null, null, 'Page 4');
```

We got:

```javascript
/*
| History stack |
| ------------- |
| Page 4 | << We are now on this page
| Page 3 |
| Page 2 |
| Page 1 |
*/
```

----

{% endcollapsible %}

### `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.

{% collapsible Example: replaceState  %}

If we have:

```javascript
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
```

After executing:

```javascript
history.replaceState(null, null, 'Page 4');
```

We got:

```javascript
/*
| History stack |
| ------------- |
| Page 4 | << We are now on this page
| Page 2 |
| Page 1 |
*/
```

----

{% endcollapsible %}

### `back`

`history.back()` will move you to the previous page in the history.

{% collapsible Example: back  %}

----

If we have:

```javascript
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
```

After executing:

```javascript
history.back()
```

We got:

```javascript
/*
| History stack |
| ------------- |
| Page 3 |
| Page 2 | << We are now on this page
| Page 1 |
*/
```

----

{% endcollapsible %}


### `forward`

`history.forward()` will move you to the next page in the history.

{% collapsible Example: forward %}

----

If we have:

```javascript
/*
| History stack |
| ------------- |
| Page 3 |
| Page 2 | << We are currently on this page
| Page 1 |
*/
```

After executing:

```javascript
history.forward()
```

We got:

```javascript
/*
| History stack |
| ------------- |
| Page 3 | << We are now on this page
| Page 2 |
| Page 1 |
*/
```

----

{% endcollapsible %}

### `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()`)

{% collapsible Example: go %}

----

If we have:

```javascript
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
```

After executing:

```javascript
history.go(-2)
```

We got:

```javascript
/*
| History stack |
| ------------- |
| Page 3 |
| Page 2 |
| Page 1 | << We are now on this page
*/
```

----

{% endcollapsible %}


## 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 to `history.pushState` or `history.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.

{% collapsible Example: replace %}

----

If we have:

```javascript
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
```

After executing:

```javascript
location.replace('Page 4')
```

We got:

```javascript
/*
| History stack |
| ------------- |
| Page 4 | << We are now on this page
| Page 2 |
| Page 1 |
*/
```

----

{% endcollapsible %}

### `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 that `assign` does you can find on [the specification](https://html.spec.whatwg.org/multipage/history.html#dom-location-assign). 

{% collapsible Example: assign %}

----

If we have:

```javascript
/*
| History stack |
| ------------- |
| Page 3 | << We are currently on this page
| Page 2 |
| Page 1 |
*/
```

After executing:

```javascript
location.assign('Page 4')
```

We got:

```javascript
/*
| History stack |
| ------------- |
| Page 4 | << We are now on this page
| Page 3 |
| Page 2 |
| Page 1 |
*/
```

----

{% endcollapsible %}


## 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](https://twitter.com/romain_trotard ) or go to my [Website](https://www.romaintrotard.com). :panda_face: