app-history
is an extension to history
designed for use in progressive web apps. The API is a superset of history
so you can use it as a drop-in replacement in react-router
for example. TypeScript definitions are included.
The primary objective for app-history
is to help developers implement back/home-buttons in progressive web apps.
When building a progressive web app you probably want to include a back-button in the user interface to support navigation in standalone mode (without browser chrome).
blah blah blah back button options
Another useful feature provided by app-history
is the ability to clear the history forward stack.
blah blah blah wizard/stepper options
Using NPM and a bundler (like webpack):
npm install --save app-history
Then create an App History object in your code like this:
import { createAppHistory } from "app-history";
const history = createAppHistory();
await history.init();
Use it with react-router
something like this:
import * as React from "react";
import { render } from "react-dom";
import { Router } from "react-router";
import { createAppHistory } from "app-history";
import { App } from "./App"; // Your app root component
// Create App History object (extending Browser History)
const history = createAppHistory();
await history.init();
// Create a <div> that will host the App component
const root = document.createElement("div");
document.body.appendChild(root);
// Tell React to render our app. Wrap it inside a Router component
// which is configured to use the App History object.
render(
<Router history={history}>
<App/>
</Router>,
root
);
Alternatively, you can load it directly from the UNPKG CDN using vanilla HTML and JavaScript:
<script src="https://unpkg.com/history/umd/history.min.js"></script>
<script src="https://unpkg.com/app-history/dist/app-history.js"></script>
Notice that you'll have to load the history
UMD package too
Then create an App History object in your code like this:
const history = AppHistory.createAppHistory({ provider: History });
history.init().then(function () {
// do stuff
});
app-history
is built for ES5 but require support for Promise
objects. To ensure compatibility you may want to load a Promise polyfill too.
TODO
TODO
TODO
Blah blah. Why it's needed and Implicit if you wish
The depth
property of an app-history
object lets you know how deep into the app you've gone, and thereby how far back you can go and still remain inside the current app session:
console.log("We can navigate back ", history.depth, " entry/entries and still be in this app session");
An history
object lets you listen on location changes and conditionally block transitions, using listen
and block
respectively.
If you which to temporarily pause notifications and prompts you can do:
const resume = history.suppress();
// this will not notify listeners or invoke block prompt
history.pushState("foo", "bar");
// resume normal processing when you're done with the secret stuff
resume();
Or using a callback action:
history.suppressWhile(() => {
// code in this callback won't notify listeners or invoke block prompt
});
suppressWhile
returns a Promise
object and will await a Promise
object returned by the callback function.
You can at any time determine whether notifications and prompts are being suppressed:
console.log("Suppression is ", history.isSuppressed ? "active" : "inactive");
app-history
return promises from all methods that may trigger a location change. These promises are resolved when the new location has been applied, or rejected in case the change is blocked.
This includes the following methods from history
:
go
goBack
goForward
push
replace
And these extension methods:
cut
findLast
goHome
init
suppressWhile
whenIdle
You can determine whether app-history
is currently processing an async operation by reading the isBusy
property:
console.log("App history is ", history.isBusy ? "busy" : "idle");
TODO
createAppHistory
will, by default, create a new browser history using createBrowserHistory
from the history
package.
You can instruct app-history
to use createMemoryHistory
(also from the history
package) instead, which is helpful when testing your code in a non-browser environment:
const history = createAppHistory({
mode: "memory"
});
If you want to provide another underlying history object you can do so (however, it is strongly recommended that you only access the underlying history object via the newly returned app-history
extension to avoid confusion):
const history = createAppHistory({
provider: myHistoryObjectProvider
});
The supplied provider object must declare a function named createBrowserHistory
when mode
is omitted or set to "browser"
, or a function named createMemoryHistory
when mode
is set to "memory"
.
app-history
will invoke the provided function with a configuration object containing a getUserConfirmation
function, no matter whether such a configuration function was passed to createAppHistory
or not.
app-history
is based on HTML5 History API state objects. So make sure that the underlying history object has support for that.
By default, app-history
will (just like history
) use window.confirm
to display a prompt when navigation is blocked. You can provide a custom prompt to createAppHistory
:
const history = createAppHistory({
getUserConfirmation(message, callback) {
callback(window.confirm(message));
}
});
Please refer to the history
package for details.
app-history
will internally store some meta information in HTML5 History API state objects. One piece of information is a cache of app-specific paths in the history back stack. By default, the cache is limited to 20 entries. If you want to change this you can do so:
const history = createAppHistory({
cacheLimit: 5 // Keep at most five paths cached in my state objects
});
If you want to disable caching:
const history = createAppHistory({
cacheLimit: 0 // No cached paths in my state objects
});
Or if you want to let the cache grow indefinately:
const history = createAppHistory({
cacheLimit: -1 // Cache 'em all!
});
You can read the currect cache limit like this:
console.log("The app history cache limit is set to: ", history.cacheLimit);