Skip to content

Commit

Permalink
Deprecate pushState and replaceState
Browse files Browse the repository at this point in the history
  • Loading branch information
taion committed Dec 6, 2015
1 parent 7bb446b commit 80371c1
Show file tree
Hide file tree
Showing 18 changed files with 231 additions and 119 deletions.
15 changes: 6 additions & 9 deletions CHANGES.md
@@ -1,20 +1,17 @@
## [HEAD]

#### New features
- Accept objects in `history.push` and `history.replace` ([#141])

#### Bug fixes
- Disable browser history on Chrome iOS ([#146])
- Do not convert same-path PUSH to REPLACE if the hash has changed ([#167])

#### Other
- Add ES2015 module build ([#152])
- **Feature:** Accept objects in `history.push` and `history.replace` ([#141])
- **Deprecation:** Deprecate `history.pushState` and `history.replaceState` in favor of passing objects to `history.push` and `history.replace` ([#168])
- **Bugfix:** Disable browser history on Chrome iOS ([#146])
- **Bugfix:** Do not convert same-path PUSH to REPLACE if the hash has changed ([#167])
- **Other:** Add ES2015 module build ([#152])

[HEAD]: https://github.com/rackt/history/compare/latest...HEAD
[#141]: https://github.com/rackt/history/pull/141
[#146]: https://github.com/rackt/history/pull/146
[#152]: https://github.com/rackt/history/pull/152
[#167]: https://github.com/rackt/history/pull/167
[#167]: https://github.com/rackt/history/pull/168

## [v1.13.1]
> Nov 13, 2015
Expand Down
3 changes: 1 addition & 2 deletions docs/BasenameSupport.md
Expand Up @@ -17,11 +17,10 @@ history.listen(function (location) {
})
```

Basename-enhanced histories also automatically prepend the basename to paths used in `pushState`, `push`, `replaceState`, `replace`, `createPath`, and `createHref`.
Basename-enhanced histories also automatically prepend the basename to paths used in `push`, `replace`, `createPath`, and `createHref`.

```js
history.createPath('/the/path') // /base/the/path
history.pushState(null, '/the/path') // push /base/the/path
history.push('/the/path') // push /base/the/path
```

Expand Down
23 changes: 11 additions & 12 deletions docs/GettingStarted.md
Expand Up @@ -27,33 +27,32 @@ unlisten()

You can also use a `history` object to programmatically change the current `location` using the following methods:

- `pushState(state, path)`
- `push(location)`
- `replaceState(state, path)`
- `replace(location)`
- `go(n)`
- `goBack()`
- `goForward()`

The [`path`](Glossary.md#path) argument to `pushState` and `replaceState` represents a complete URL path, including the [search string](Glossary.md#search) and [hash](Glossary.md#hash). The [`state`](Glossary.md#locationstate) argument should be a JSON-serializable object.
The `push` and `replace` methods take a [path string](Glossary.md#path) that represents a complete URL path, including the [search string](Glossary.md#search) and [hash](Glossary.md#hash).

The location argument to `push` and `replace` can be either a path string as above or a [location descriptor](Glossary.md#locationdescriptor) object representing the next history entry, including the state.
They can also accept a [location descriptor](Glossary.md#locationdescriptor) object that defines the path as a combination of [`pathname`](Glossary.md#pathname), [`search`](Glossary.md#search), and [`hash`](Glossary.md#hash). This object can also include [`state`](Glossary.md#locationstate) as a JSON-serializable object.

```js
// Push a new entry onto the history stack.
history.pushState({ some: 'state' }, '/home')
history.push('/home')

// Replace the current entry on the history stack.
history.replaceState({ some: 'other state' }, '/profile')
history.replace('/profile')

// Push a path with null state.
history.push('/about')

// Push a new history location object with state.
history.push({ pathname: '/contact', state: { some: 'state' } })
// Push a new entry with state onto the history stack.
history.push({
pathname: '/about',
search: '?the=search',
state: { some: 'state' }
})

// Change just the search on an existing location.
history.push({ ...location, search: '?the=search' })
history.push({ ...location, search: '?the=other+search' })

// Go back to the previous history entry. The following
// two lines are synonymous.
Expand Down
2 changes: 0 additions & 2 deletions docs/Glossary.md
Expand Up @@ -64,9 +64,7 @@ A *hash* is a string that represents the hash portion of the URL. It is synonymo
listenBefore: (hook: TransitionHook) => Function;
listen: (listener: LocationListener) => Function;
transitionTo(location: Location) => void;
pushState(state: LocationState, path: Path) => void;
push(location: LocationDescriptor) => void;
replaceState(state: LocationState, path: Path) => void;
replace(location: LocationDescriptor) => void;
go(n: number) => void;
goBack() => void;
Expand Down
3 changes: 1 addition & 2 deletions docs/QuerySupport.md
Expand Up @@ -23,10 +23,9 @@ history.listen(function (location) {
})
```

Query-enhanced histories accept URL queries as trailing arguments to `pushState`, `replaceState`, `createPath`, and `createHref`, and accept `query` as a key for `push` and `replace`.
Query-enhanced histories accept URL queries as trailing arguments to `createPath`, and `createHref`, and accept `query` as a key for `push` and `replace`.

```js
history.createPath('/the/path', { the: 'query' })
history.pushState(null, '/the/path', { the: 'query' })
history.push({ pathname: '/the/path', query: { the: 'query' } })
```
32 changes: 25 additions & 7 deletions modules/__tests__/MemoryHistory-test.js
Expand Up @@ -21,26 +21,41 @@ describe('memory history', function () {
describeQueries(createMemoryHistory)
describeGo(createMemoryHistory)

describe('when using pushState in the middle of the stack', function () {
describe('when using push in the middle of the stack', function () {
it('clears rest of stack so the user cannot go forward', function () {
let history = createMemoryHistory(), location

history.listen(function (loc) {
location = loc
})

history.pushState({ id: 1 }, '/1')
history.pushState({ id: 2 }, '/2')
history.pushState({ id: 3 }, '/3')
history.pushState({ id: 4 }, '/4')
history.push({
pathname: '/1',
state: { id: 1 }
})
history.push({
pathname: '/2',
state: { id: 2 }
})
history.push({
pathname: '/3',
state: { id: 3 }
})
history.push({
pathname: '/4',
state: { id: 4 }
})

expect(location.state).toEqual({ id: 4 })

history.go(-2)

expect(location.state).toEqual({ id: 2 })

history.pushState({ id: 5 }, '/5')
history.push({
pathname: '/5',
state: { id: 5 }
})

expect(location.state).toEqual({ id: 5 })
expect(location.pathname).toEqual('/5')
Expand All @@ -59,7 +74,10 @@ describe('memory history', function () {
}).toThrow(/Cannot go\(\d+\) there is not enough history/)

history.goBack()
history.pushState({ id: 6 }, '/6')
history.push({
pathname: '/6',
state: { id: 6 }
})

expect(function () {
history.goForward()
Expand Down
7 changes: 5 additions & 2 deletions modules/__tests__/describeBasename.js
Expand Up @@ -243,7 +243,7 @@ function describeBasename(createHistory) {
})
})

describe('in pushState', () => {
describe('in push', () => {
it('works', function (done) {
let steps = [
function (location) {
Expand All @@ -253,7 +253,10 @@ function describeBasename(createHistory) {
expect(location.action).toEqual(POP)
expect(location.basename).toEqual('')

history.pushState({ the: 'state' }, '/home')
history.push({
pathname: '/home',
state: { the: 'state' }
})
},
function (location) {
expect(location.pathname).toEqual('/home')
Expand Down
12 changes: 10 additions & 2 deletions modules/__tests__/describeGo.js
Expand Up @@ -23,7 +23,11 @@ function describeGo(createHistory) {
expect(location.state).toEqual(null)
expect(location.action).toEqual(POP)

history.pushState({ the: 'state' }, '/home?the=query')
history.push({
pathname: '/home',
search: '?the=query',
state: { the: 'state' }
})
},
function (location) {
expect(location.pathname).toEqual('/home')
Expand Down Expand Up @@ -54,7 +58,11 @@ function describeGo(createHistory) {
expect(location.state).toEqual(null)
expect(location.action).toEqual(POP)

history.pushState({ the: 'state' }, '/home?the=query')
history.push({
pathname: '/home',
search: '?the=query',
state: { the: 'state' }
})
},
function (location) {
expect(location.pathname).toEqual('/home')
Expand Down
9 changes: 7 additions & 2 deletions modules/__tests__/describeHashSupport.js
Expand Up @@ -23,7 +23,12 @@ function describeHashSupport(createHistory) {
expect(location.state).toEqual(null)
expect(location.action).toEqual(POP)

history.pushState({ the: 'state' }, '/home?the=query#the-hash')
history.push({
pathname: '/home',
search: '?the=query',
hash: '#the-hash',
state: { the: 'state' }
})
},
function (location) {
expect(location.pathname).toEqual('/home')
Expand All @@ -46,7 +51,7 @@ function describeHashSupport(createHistory) {
expect(location.state).toEqual(null)
expect(location.action).toEqual(POP)

history.pushState(null, '/#the-hash')
history.push('/#the-hash')
},
function (location) {
expect(location.pathname).toEqual('/')
Expand Down
5 changes: 4 additions & 1 deletion modules/__tests__/describeInitialLocation.js
Expand Up @@ -29,7 +29,10 @@ function describeInitialLocation(createHistory) {

it('emits POP with current location key', function (done) {
// set initial state, this is needed because all implementations gets state from different places
history.pushState({ initial: 'state' }, '/')
history.push({
pathname: '/',
state: { initial: 'state' }
})

// now create history for testing if initial POP event has location.key
history = createHistory()
Expand Down
4 changes: 2 additions & 2 deletions modules/__tests__/describePopState.js
Expand Up @@ -4,7 +4,7 @@ function describePopState(createHistory) {

beforeEach(function () {
history = createHistory()
history.pushState(null, '/home')
history.push('/home')
})

afterEach(function () {
Expand All @@ -26,7 +26,7 @@ function describePopState(createHistory) {

beforeEach(function () {
history = createHistory()
history.pushState(null, '/home')
history.push('/home')
})

afterEach(function () {
Expand Down
39 changes: 38 additions & 1 deletion modules/__tests__/describePush.js
@@ -1,5 +1,5 @@
import expect from 'expect'
import { PUSH, POP } from '../Actions'
import { PUSH, POP, REPLACE } from '../Actions'
import execSteps from './execSteps'

function describePush(createHistory) {
Expand Down Expand Up @@ -92,6 +92,43 @@ function describePush(createHistory) {

unlisten = history.listen(execSteps(steps, done))
})

it('becomes a REPLACE if path is unchanged', function (done) {
let steps = [
function (location) {
expect(location.pathname).toEqual('/')
expect(location.search).toEqual('')
expect(location.state).toEqual(null)
expect(location.action).toEqual(POP)

history.push({
pathname: '/home',
search: '?the=query',
state: { the: 'state' }
})
},
function (location) {
expect(location.pathname).toEqual('/home')
expect(location.search).toEqual('?the=query')
expect(location.state).toEqual({ the: 'state' })
expect(location.action).toEqual(PUSH)

history.push({
pathname: '/home',
search: '?the=query',
state: { different: 'state' }
})
},
function (location) {
expect(location.pathname).toEqual('/home')
expect(location.search).toEqual('?the=query')
expect(location.state).toEqual({ different: 'state' })
expect(location.action).toEqual(REPLACE)
}
]

unlisten = history.listen(execSteps(steps, done))
})
})
})
}
Expand Down
8 changes: 6 additions & 2 deletions modules/__tests__/describeQueryKey.js
Expand Up @@ -22,7 +22,7 @@ function describeQueryKey(createHistory) {
expect(location.state).toEqual(null)
expect(location.action).toEqual(POP)

history.pushState(null, '/home?the=query')
history.push('/home?the=query')
},
function (location) {
expect(location.pathname).toEqual('/home')
Expand Down Expand Up @@ -71,7 +71,11 @@ function describeQueryKey(createHistory) {
expect(location.state).toEqual(null)
expect(location.action).toEqual(POP)

history.pushState({ the: 'state' }, '/home?the=query')
history.push({
pathname: '/home',
search: '?the=query',
state: { the: 'state' }
})
},
function (location) {
expect(location.pathname).toEqual('/home')
Expand Down
22 changes: 17 additions & 5 deletions modules/__tests__/describeTransitions.js
Expand Up @@ -21,7 +21,11 @@ function describeTransitions(createHistory) {
it('receives the next location', function (done) {
let steps = [
function () {
history.pushState({ the: 'state' }, '/home?the=query')
history.push({
pathname: '/home',
search: '?the=query',
state: { the: 'state' }
})
},
function (location) {
expect(nextLocation).toBe(location)
Expand Down Expand Up @@ -54,7 +58,11 @@ function describeTransitions(createHistory) {
it('receives the next location', function (done) {
let steps = [
function () {
history.pushState({ the: 'state' }, '/home?the=query')
history.push({
pathname: '/home',
search: '?the=query',
state: { the: 'state' }
})
},
function (location) {
expect(nextLocation).toBe(location)
Expand Down Expand Up @@ -103,7 +111,11 @@ function describeTransitions(createHistory) {

it('updates the location', function () {
let prevLocation = location
history.pushState({ the: 'state' }, '/home?the=query')
history.push({
pathname: '/home',
search: '?the=query',
state: { the: 'state' }
})
expect(prevLocation).toNotBe(location)

assert(location)
Expand Down Expand Up @@ -147,7 +159,7 @@ function describeTransitions(createHistory) {

it('does not update the location', function () {
let prevLocation = location
history.pushState(null, '/home')
history.push('/home')
expect(prevLocation).toBe(location)
})
})
Expand Down Expand Up @@ -178,7 +190,7 @@ function describeTransitions(createHistory) {

it('does not update the location', function () {
let prevLocation = location
history.pushState(null, '/home')
history.push('/home')
expect(prevLocation).toBe(location)
})
})
Expand Down

0 comments on commit 80371c1

Please sign in to comment.