This document describes the overall React architecture of Progressive Web builds. It is current with projects generated after March 6, 2017, and does not completely describe builds generated before February 2017.
The Root Component
The root of the component tree is the
Router component, defined in
app/router.jsx. This component does two things:
- it creates the Redux store provider
- it includes the app router, which matches URL paths to React components
It does not render any visible components or UI, but is only concerned with the overall structure of the app.
We render an overall
App component on the root path, with the remainder of the
router selecting a
Template component to render as the main body of the page.
App Component #
App component is rendered on all routes and manages the global UI, such as headers or sidebars. It is the first component on the tree to render actual DOM elements rather than just selecting React components.
This is where app-level elements such as the SVG sprite sheet and accessibility skip links are rendered. It also handles offline notification, including the replacement of the template with an offline status screen if a page is not available.
The routed template is passed as a child element of the
App component, and must be rendered by it alongside the global elements
Templates and the
template Higher Order Component #
The main content of the page, for any given route, is that page’s template. At any time, there can only be one template mounted in the component tree.
Templates are React components, connected or disconnected, that are wrapped in the
template higher order component. This higher-order component handles changes in the Redux store that need to happen between the unmounting of one component and the mounting of another. This includes triggering data fetches from the backend, changing the current route in the Redux store, and, if necessary, communicating with the Progressive App framework. The
template component is defined in
template.jsx in the
web/app directory of your project; this will move into the SDK as it matures.
The templates are defined in the
containers/templates.js file, to avoid circular dependencies. This file just imports the components for each of the templates, wraps them in the
template() function, and re-exports them for use in the
Router. Do not wrap with the
template() function in
router.jsx, as different routes will then have different wrappers on their template components, even if the underlying component is the same.
Currently, templates and non-templates are mixed together in the
app/containers/ directory; in future this will change.
Template Partials #
Ideally, each top-level template component should have minimal logic, only rendering the high-level parts of the page. These parts are React components called partials, stored in the subdirectory of the same name. We recommend each partial’s name begin with the name of the template component to help developers easily identify which partial belongs to which template. There may be multiple levels of components in the
Wherever possible, partials should get their props by directly connecting to the the Redux store, rather than passing them in from the store through their parent components. In particular, avoid centralizing the store connection in the template component. This allows us to optimize updates and removes clutter from the code.
Modal Components #
Much like templates, modals are just React components responsible for displaying contextual content. However, unlike templates which are controlled by the router, modals are registered to and controlled by the Modal Manager. Learn how to create, show, and hide modals in the Getting Started: Adding a Modal article.
Local Components #
Any custom components that are not tied to a specific template or modal can be built in the
app/components/ directory. This directory contains React components which do not have a branch in the Redux store, but it can contain components that are connected to the Redux store for receiving data and dispatching actions.