Skip to content
This repository has been archived by the owner on Jul 15, 2019. It is now read-only.

Commit

Permalink
Add handling for pre-render popstate events
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Ridgway committed Oct 29, 2015
1 parent 036b32e commit ece3eb9
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
23 changes: 23 additions & 0 deletions lib/handleHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ var defaultOptions = {
}
};

// Begin listening for popstate so they are not missed prior to instantiation
// this could be if the user uses back button multiple times before
// handleHistory componentDidMount fires
var EVENT_POPSTATE = 'popstate';
var HAS_PUSH_STATE = !!(typeof window !== 'undefined' && window.history && window.history.pushState);
var lastPendingPopstateEvent = null;
function preloadListener() {
lastPendingPopstateEvent = arguments;
}
if (HAS_PUSH_STATE) {
window.addEventListener(EVENT_POPSTATE, preloadListener);
}

// Used for ensuring that only one history handler is created
var historyCreated = false;

Expand Down Expand Up @@ -78,6 +91,16 @@ function createComponent(Component, opts) {
}
this._history.on(this._onHistoryChange);

if (HAS_PUSH_STATE) {
// We're ready to start handling the last popstate that fired
// before the history handler was mounted.
window.removeEventListener(EVENT_POPSTATE, preloadListener);
if (lastPendingPopstateEvent) {
this._onHistoryChange.apply(this, lastPendingPopstateEvent);
lastPendingPopstateEvent = null;
}
}

window.addEventListener('scroll', this._onScroll);
},
_onScroll: function (e) {
Expand Down
17 changes: 17 additions & 0 deletions tests/unit/lib/handleHistory-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,23 @@ describe('handleHistory', function () {
expect(mockContext.executeActionCalls[0].payload.url).to.equal(window.location.pathname);
expect(mockContext.executeActionCalls[0].payload.params).to.deep.equal({a: 1});
});
it('handle pre-emptive popstate events', function (done) {
var MockAppComponent = mockCreator();
window.dispatchEvent({_type: 'popstate', state: {params: {a: 1}}});
window.dispatchEvent({_type: 'popstate', state: {params: {a: 2}}});
window.dispatchEvent({_type: 'popstate', state: {params: {a: 3}}});
setTimeout(function () {
ReactTestUtils.renderIntoDocument(
<MockAppComponent context={mockContext} />
);
expect(mockContext.executeActionCalls.length).to.equal(1);
expect(mockContext.executeActionCalls[0].action).to.be.a('function');
expect(mockContext.executeActionCalls[0].payload.type).to.equal('popstate');
expect(mockContext.executeActionCalls[0].payload.url).to.equal(window.location.pathname);
expect(mockContext.executeActionCalls[0].payload.params).to.deep.equal({a: 3});
done();
}, 10);
});
it('listen to scroll event', function (done) {
var routeStore = mockContext.getStore('RouteStore');
routeStore._handleNavigateStart({url: '/the_path_from_state', method: 'GET'});
Expand Down

0 comments on commit ece3eb9

Please sign in to comment.