An application instance is the object that brings a state manager and renderer together to represent a running frontend application. It manages lifecycle work: holding state, rendering views, and responding to user input. section 5.2 section 5.2.1
A basic application instance coordinates:
- Initial state, reducers, and the top-level component supplied by the developer. section 5.2.1
- A renderer and state manager instantiated and connected by the framework. section 5.2.1
- A mount() method that receives a DOM element and starts the application lifecycle. section 5.2.1
- Rendering that replaces the current DOM tree and mounts a new view when rendering occurs. section 5.2.2
Minimal renderer
createApp({ state, view }) keeps parentEl and the previous virtual DOM in a closure. mount() saves the parent element, computes view(state), and mounts the result. Later, the state manager can trigger another render. section 5.2.2
Listing 5.5 The application instance with its renderer (app.js)
import { destroyDOM } from './destroy-dom'
import { mountDOM } from './mount-dom'
export function createApp({ state, view }) { #1
let parentEl = null
let vdom = null
function renderApp() {
if (vdom) {
destroyDOM(vdom) #2
}
vdom = view(state)
mountDOM(vdom, parentEl) #3
}
return {
mount(_parentEl) { #4
parentEl = _parentEl
renderApp()
},
}
}
Inspect the incremental JavaScript implementation of createApp(), including virtual-DOM tracking, rendering, and mounting. section 5.2.2
Listing 12.7 The application instance (app.js)
import { mountDOM } from './mount-dom'
import { destroyDOM } from './destroy-dom'
import { h } from './h'
export function createApp(RootComponent, props = {}) { #1
let parentEl = null
let isMounted = false
let vdom = null
function reset() { #2
parentEl = null
isMounted = false
vdom = null
}
return {
mount(_parentEl) {
if (isMounted) { #3
throw new Error('The application is already mounted')
}
parentEl = _parentEl #4
vdom = h(RootComponent, props) #5
mountDOM(vdom, parentEl) #6
isMounted = true
},
unmount() {
if (!isMounted) { #7
throw new Error('The application is not mounted')
}
destroyDOM(vdom) #8
reset() #9
},
}
}
Compare the later component-based design, where createApp() accepts a root component and props, exposes mount() and unmount(), and rejects invalid lifecycle calls. section 12.4
