Web browser history¶
By default Child Stack
navigation does not affect URLs in the browser address bar. But sometimes it is necessary to have different URLs for different Child Stack
destinations. For this purpose Decompose provides an experimental API - WebHistoryController.
The controller listens for the Child Stack
state changes and updates the browser URL and the history accordingly:
- When one or more components are pushed to the
Child Stack
stack, the controller pushes corresponding pages to the history - When one or more components are popped from the stack, the controller pops corresponding pages from the history
- When some components are replaced in the stack, the controller tries its best to keep the page history aligned (there are corner cases)
- When the user presses the browser's Back button (or selects one of the previous pages in the history dropdown menu), the controller pops the corresponding configurations from the
Child Stack
- When the user navigates forward in the browser history, the controller pushes the corresponding configurations to the
Child Stack
Corner cases¶
There is one known corner case due to the History API limitations. When all configurations in the stack are replaced with another single configuration (A
<-B
<-C
===> D
), the pages corresponding to the second and subsequent removed configurations (B
and C
) remain in the history. If at this point the user will move forward (by clicking on the Forward button in the browser), the previously removed configurations will be pushed back to the stack (the stack will become D
<-B
or D
<-B
<-C
).
Limitations¶
Only one Child Stack
can be attached to an instance of the WebHistoryController
. Having multiple instances of the controller is not allowed.
Configuring the application¶
Using WebHistoryController
in a single page application requires additional configuration - a catch-all strategy to return the same html resource for all paths. This strategy will be different for different server configurations.
Development configuration¶
The Kotlin/JS browser
target uses webpack-dev-server as a local development server. It can be configured to use the same index.html
file (or your primary html file) for all paths, by setting the devServer.historyApiFallback flag. The Gradle DSL for Kotlin webpack currently does not support the historyApiFallback
flag, so a special configuration file should be used instead.
First, create a directory named webpack.config.d
in the JS app module's directory. Then create a new file named devServerConfig.js
inside that directory. Finally, put the following content to the file:
// <js app module>/webpack.config.d/devServerConfig.js
config.devServer = {
...config.devServer, // Merge with other devServer settings
"historyApiFallback": true
};
Using the WebHistoryController¶
Using WebHistoryController
is easy:
- Create an instance of
DefaultWebHistoryController
in the JS app and pass it via constructor to a component responsible for navigation (typically it is the root component). - Create
Child Stack
and useWebHistoryController#historyPaths
property for initial stack. This is required for cases when the page is reloaded (refreshed), so that the stack is aligned with te browser history. - In the component, call the
WebHistoryController.attach
method and supply all arguments. - In the JS app, pass an initial deeplink to the component.
- Use the deeplink in the component to generate an initial back stack.
Example¶
The sample project demonstrates the use of WebHistoryController
:
- Main.kt - demonstrates passing
WebHistoryController
and a deeplink via constructor toRootComponent
- RootComponent - demonstrates generating the initial stack from the deeplink, as well as calling
WebHistoryController.attach
and supplying the arguments